4

I was under the impression that within single quotes, e.g. 'pattern', bash special characters are not interpolated, so one need only escape single quotes themselves.

Why then does echo "123" | grep '[0-9]+' output nothing, whereas echo "123" | grep '[0-9]\+' (plus sign escaped) output 123? (Likewise, echo "123" | grep '3|4' outputs nothing unless you escape the |.)

This is under bash 4.1.2 and grep 2.6.3 on CentOS 6.5.

Community
  • 1
  • 1
Kev
  • 15,899
  • 15
  • 79
  • 112

2 Answers2

8

grep uses Basic Regular Expressions, like sed and vi. In that you have to escape metacharacters, and it is tedious.

You probably want Extended Regular Expressions, so use egrep or grep -E (depending on the version in use). Check your man grep.

See also the GNU documentation for a full list of the characters involved.

Most languages use Extended Regular Expressions (EREs) these days, and they are much easier to use. Basic Regular Expressions (BREs) are really a throw-back.

cdarke
  • 42,728
  • 8
  • 80
  • 84
  • 2
    To clarify: extended regular expressions are not a GNU-ism. They are fully [part of POSIX](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_04). – kojiro Aug 06 '15 at 10:53
  • @kojiro: yes, both are POSIX. The GNU documentation has a clear paragraph showing the differences which is why I linked it. – cdarke Aug 06 '15 at 10:56
2

That seems to be the regular expression engine that grep uses. If you use a different one, it works:

$ echo "123" | grep '[0-9]+'
$ echo "123" | grep -P '[0-9]+'
123
$ echo "123" | grep '3|4'
$ echo "123" | grep -P '3|4'
123
chw21
  • 7,970
  • 1
  • 16
  • 31