Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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

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

What does \? stand for?

share|improve this question
add comment

3 Answers

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:

share|improve this answer
    
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. –  Keith Thompson Nov 5 '11 at 21:30
add comment

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

share|improve this answer
add comment

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.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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