16

The following command is used to search for a 7-digit phone number:

grep "[[:digit:]]\{3\}[ -]\?[[:digit:]]\{4\}" file

What does \? stand for?

0

3 Answers 3

23

It's like ? in many other regular expression engines, and means "match zero or one of whatever came before it".

In your example, the \? is applied to the [ -], meaning it tries to match a space or a minus, but that the space or minus is optional.

So any of these will match:

555 1234
555-1234
5551234

The reason it's written as \? rather than ? is for backwards compatibility.

The original version of grep used a different type of regular expression called a "basic regular expression" where ? just meant a literal question mark.

So that GNU grep could have the zero or one functionality, they added it, but had to use the \? syntax so that scripts that used ? still worked as expected.

Note that grep has an -E option which makes it use the more common type of regular expression, called "extended regular expressions".

man 1 grep:

   -E, --extended-regexp
          Interpret PATTERN as an extended regular expression
          (ERE, see below).  (-E is specified by POSIX.)

   -G, --basic-regexp
          Interpret PATTERN as a basic regular expression (BRE, see below).
          This is the default.

...

Repetition
    A regular expression may be followed by one of several repetition operators:
    ?      The preceding item is optional and matched at most once.

...

    grep understands three different versions of regular expression syntax:
    “basic,” “extended” and “perl.”

...

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

Further info:

3
  • The egrep command is equivalent to grep -E. For versions other than GNU grep, grep might or might not accept the -E option, and egrep might be a separate program. Commented Nov 5, 2011 at 21:30
  • @KeithThompson, grep -E is the official POSIX way. egrep was deprecated in susv2 (1997) and removed in susv3 (2001) from the POSIX and Unix specs. Commented Dec 8, 2014 at 0:50
  • 1
    \? is a GNUism though. Commented Dec 8, 2014 at 0:51
9

Unfortunately, the exact syntax of regular expressions varies slightly between different programs: grep regexes aren't exactly the same as sed regexes, which aren't exactly the same as Emacs regexes, which aren't exactly the same as C++ regexes, and so on. To make matters worse, even a "standard" tool like grep can vary slightly between different Unix-like operating systems.

In a regex, some characters have special meaning (such as the square brackets in your example), and revert to their normal meaning as literal characters when you "escape" them by putting a backslash in front of them (so a literal bracket would be written as \[). Others work the other way around, and only take on special meaning when escaped (e.g. plain n is just a letter, but \n is a line feed). And these, again, can vary between regex implementations.

In most regex implementations, a question mark means that the previous item is optional, while an escaped question mark (\?) is a literal question mark. But in a few dialects, it's the other way around. Your example could make sense either way around, but I suspect you have one of the dialects where ? is a literal and \? is the optional symbol. So your regex probably means "three digits, optionally followed by a space or dash, followed by four digits".

(Another clue can be seen in constructs like \{3\}, which is clearly intended to mean "exactly 3 of the previous item". In most regex dialects this would be written {3}, and \{ would be a literal brace.)

6

This is a quick summary of information that's already contained in the other answers.

In grep, ? matches a literal question-mark character, and \? denotes zero or one occurrence of whatever precedes it. So in the example in your question, [ -]\? matches either a space, or a hyphen, or nothing.

In egrep or grep -E, it's the other way around; \? matches a literal question mark, and ? denotes zero or one occurrence.

This applies to GNU grep; the details for non-GNU grep implementations may differ slightly. In particular, grep and egrep were historically two separate programs, and I don't think old greps had the -E option. POSIX does specify grep -E, but (I was surprised to discover) doesn't mention egrep.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .