49

This

ls -l /var/log | awk '{print $9}' | grep "^[a-z]*\.log."

outputs this:

alternatives.log.1
alternatives.log.10.gz
alternatives.log.2.gz
alternatives.log.3.gz
alternatives.log.4.gz
alternatives.log.5.gz
alternatives.log.6.gz
alternatives.log.7.gz
alternatives.log.8.gz
alternatives.log.9.gz
apport.log.1
apport.log.2.gz
apport.log.3.gz

but this:

ls -l /var/log | awk '{print $9}' | grep "^[a-z]+\.log."

outputs nothing.

Why? I just changed * to +. Isn't it similar? Operator + just needs at least one match, and * zero or more.

Seth
  • 58,122
Marko
  • 762

2 Answers2

56

This is because grep (without any arguments) only works with standard regular expressions. + is part of the extended regular expressions, so to use that, you need to use grep -E or egrep:

ls -l /var/log | awk '{print $9}' | grep -E "^[a-z]+\.log."

Also, you can just do this if you don't want to use extended regular expressions:

ls -l /var/log | awk '{print $9}' | grep "^[a-z][a-z]*\.log."
MiJyn
  • 3,336
  • Thanks. I now about that workaround, but I was wondering why "+" does not work. Now I know. Thanks again. – Marko May 09 '13 at 17:57
16

To elaborate on MiJyns answer, "special characters" like + do work in standard regex as well, but you need to escape them with a backslash. You might say, the default expectations are reversed between standard and extended regex:

In standard regex, characters match literally by default. For example, in grep "ab+" the + is a literal +. The regex would for example find "ab+ab", but not "abbbb". To use the "special meaning" of +, you need to escape it. So grep "ab\+" would find "abbb", but not "ab+ab" any longer. Because in the last example, the + is interpreted as the quantifier "one or many of that", in that case "one or many b".

In extended regex it's exactly the other way around. Here, you need to escape "special characters" to be treated literally. So grep -E "ab+" finds "abbb", but not "ab+ab". If you escape the +, it get's matched literally. So grep -E "ab\+" finds "ab+ab", but not "abbb".

  • 1
    What a legacy mess... ;-) like magic and supermagic re in vim. Urgh. The price to pay for backward compatibility... – Rmano Nov 09 '15 at 10:32
  • Just pointing out that it's not because the plus didnt get escaped. plus is flat out not supported in non-extended regex grep (see other answer)... This is good to keep in mind though, still: if in doubt, you can try escaping your regex special characters. Might do the trick. – Steven Lu Nov 09 '22 at 23:37