Ubuntu: grep “+” operator does not work



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.


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."  


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".

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Next Post »