Что значит \? значит в регулярном выражении?


16

Следующая команда используется для поиска 7-значного номера телефона:

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

Что означает \??

Ответы:


21

Это как ? во многих других механизмах регулярных выражений, и означает «соответствовать нулю или одному из того, что было до него».

В вашем примере, объект \?применяется к [ -], то есть он пытается найти пробел или минус, но пробел или минус необязателен.

Таким образом, любой из них будет соответствовать:

555 1234
555-1234
5551234

Причина написана как \? а не ?для обратной совместимости.

Оригинальная версия grepиспользовала другой тип регулярного выражения, называемого «базовое регулярное выражение», где? просто означало буквальный знак вопроса.

Чтобы GNU grep мог иметь нулевую или одну функциональность, они добавили его, но должны были использовать \?синтаксис, чтобы скрипты, которые использовали? работали, как и ожидалось.

Обратите внимание, что grep имеет -E опция, которая заставляет его использовать более распространенный тип регулярных выражений, называемый «расширенные регулярные выражения».

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

Дополнительная информация:


Команда egrepэквивалентна grep -E. Для версий, отличных от GNU grep, grepможет принимать или не принимать эту -Eопцию и egrepможет быть отдельной программой.
Кит Томпсон

@KeithThompson, grep -Eэто официальный способ POSIX. egrepустарел в susv2 (1997) и удален в susv3 (2001) из спецификаций POSIX и Unix.
Стефан Шазелас

1
\?это GNUism, хотя.
Стефан Шазелас

8

К сожалению, точный синтаксис регулярных выражений немного различается в разных программах: регулярные выражения grep не совсем совпадают с регулярными выражениями sed, которые не совсем совпадают с регулярными выражениями Emacs, которые не совсем совпадают с регулярными выражениями C ++, и поэтому на. Что еще хуже, даже «стандартный» инструмент, такой как grep, может незначительно отличаться в разных Unix-подобных операционных системах.

В регулярном выражении некоторые символы имеют особое значение (например, квадратные скобки в вашем примере) и возвращаются к своему обычному значению в виде буквенных символов, когда вы «экранируете» их, помещая перед ними обратную косую черту (так что буквенная скобка будет записывается как \ [). Другие работают наоборот и приобретают особое значение только после экранирования (например, обычное n - просто буква, а \ n - перевод строки). И они, опять же, могут варьироваться между реализациями регулярных выражений.

В большинстве реализаций регулярных выражений знак вопроса означает, что предыдущий элемент является необязательным, а экранированный знак вопроса (\?) - буквальный знак вопроса. Но на нескольких диалектах все наоборот. Ваш пример может иметь смысл в любом случае, но я подозреваю, что у вас есть один из диалектов, где? это буквальное и \? это необязательный символ. Таким образом, ваше регулярное выражение, вероятно, означает «три цифры, за которыми, возможно, следует пробел или тире, за которыми следуют четыре цифры».

(В подсказках типа \ {3 \} можно увидеть другую подсказку, которая явно предназначена для обозначения «ровно 3 из предыдущего элемента». На большинстве диалектов регулярных выражений это будет написано {3}, а \ {будет литеральной скобкой .)


6

Это краткое изложение информации, которая уже содержится в других ответах.

In grep, ?соответствует буквальному символу знака вопроса и \?обозначает ноль или одно вхождение того, что ему предшествует. Так что в примере в вашем вопросе [ -]\?соответствует либо пробел, либо дефис, либо ничего.

В egrepили grep -Eнаоборот; \?соответствует буквальному вопросительному знаку и ?обозначает ноль или одно вхождение.

Это относится к GNU grep; детали реализации grep не GNU могут немного отличаться. В частности, grepи egrepбыли исторически две отдельных программы, и я не думаю , что старый greps имел -Eвариант. POSIX действительно указывает grep -E, но (я был удивлен, обнаружив) не упоминает egrep.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.