Що значить \? означають у регулярному виразі?


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

Це швидкий підсумок інформації, який вже міститься в інших відповідях.

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

У egrepабо grep -E, навпаки; \?відповідає буквальному знаку запитання і ?позначає нуль або один випадок.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.