5

I did some simple tests with grep '+' and '*' special character

$ echo 'where wh+'> /tmp/toto
$ grep 'wh[e]\*' /tmp/toto
$ grep 'wh[e]*' /tmp/toto
where wh+
$ grep 'wh[e]+' /tmp/toto
$ grep 'wh+' /tmp/toto
$ grep 'wh[e]\+' /tmp/toto
where
$ grep -E 'wh[e]*' /tmp/toto
where wh+
$ grep -E 'wh[e]+' /tmp/toto
where wh+

From theses tests, non extended grep '+' (and '?') is not interpreted as a special character, in order to use it as a special character it must be escaped. As I read, grep uses Basic Regular Expressions (without -E option), in this case, special characters are defined here : http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_03 and '?' '+' are not special characters for BRE.

But why does escaping non special character '+' in a BRE makes it special character?

7

This is a GNU extension. From the grep(1) manpage:

In GNU grep, there is no difference in available functionality between basic and extended syntaxes. In other implementations, basic regular expressions are less powerful. The following description applies to extended regular expressions; differences for basic regular expressions are summarized afterwards.

and further down

Basic vs Extended Regular Expressions

In basic regular expressions the meta-characters ?, +, {, |, (, and ) lose their special meaning; instead use the backslashed versions \?, \+, \{, \|, \(, and \).

0

I don't quite see which of the examples above to you seems to violate the defined behaviour?

No escaping of + changes the rules.

0

At that link to the POSIX specification you gave, you can read:

An ordinary character is a BRE that matches itself: any character in the supported character set, except for the BRE special characters listed in BRE Special Characters.

The interpretation of an ordinary character preceded by a ( '\' ) is undefined, except for:

  • The characters ')', '(', '{', and '}'
  • The digits 1 to 9 inclusive (see BREs Matching Multiple Characters)
  • A character inside a bracket expression

So basically, since + is an ordinary BRE character, the behaviour of grep 'x\+' is unspecified, some implementations like GNU grep treat it the same as grep 'x\{1,\}' (grep -E 'x+'), some the same as grep 'x+' some may treat is the same as grep 'x\\+' or anything else.

So if you mean to match the string x\+ portably, you should write grep 'x\\+' (or grep 'x[\]+', or grep -F 'x\+' or grep -E 'x\\\+' or grep -E 'x[\][+]').

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.