web-dev-qa-db-fra.com

Qu'est-ce que \? signifie dans une expression régulière?

La commande suivante est utilisée pour rechercher un numéro de téléphone à 7 chiffres:

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

Que fait \? représenter?

16
user5997

C'est comme ? Dans de nombreux autres moteurs d'expression réguliers, et signifie "Match zéro ou l'un de tout ce qui est venu avant cela".

Dans votre exemple, le \? est appliqué au [ -], ce qui signifie qu'il essaie de faire correspondre un espace ou un moins, mais que l'espace ou moins est facultatif.

Donc, l'une d'entre elles correspondra:

555 1234
555-1234
5551234

La raison pour laquelle il est écrit comme \? plutôt que ? est pour la compatibilité en arrière.

La version originale de grep a utilisé un type différent d'expression régulière appelée "expression régulière de base" où ? signifiait juste un point d'interrogation littéral.

Donc que GNU grep pourrait avoir la fonctionnalité zéro ou une fonctionnalité, ils l'ont ajouté, mais devaient utiliser le \? Syntaxe de sorte que les scripts utilisés ? toujours travaillé comme prévu.

Notez que grep a un -E Option qui permet d'utiliser le type d'expression régulier plus courant, appelé "expressions régulières étendues".

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

Plus d'infos:

21
Mikel

Malheureusement, la syntaxe exacte des expressions régulières varie légèrement entre différents programmes: les regextes Grep ne sont pas exactement les mêmes que les regex de SED, qui ne sont pas exactement les mêmes que les expressions d'Emacs, qui ne sont pas exactement les mêmes que c ++ Regexes, etc. au. Pour aggraver les choses, même un outil "standard" comme Grep peut varier légèrement entre différents systèmes d'exploitation de type UNIX.

Dans une regex, certains caractères ont une signification particulière (comme les crochets dans votre exemple) et revenir à leur sens normal comme des personnages littéraux lorsque vous les "échapper à" en mettant une barre oblique inverse devant eux (donc un support littéral serait écrit comme\[). D'autres travaillent dans l'inverse, et n'en prennent que sur une signification particulière lorsqu'il est échappé (par exemple, une seule lettre, mais\N est une alimentation en ligne). Et celles-ci, encore une fois, peuvent varier entre les implémentations des regex.

Dans la plupart des implémentations des regex, un point d'interrogation signifie que l'élément précédent est facultatif, tandis qu'une marque d'interrogation évasée (\?) Est une note d'interrogation littérale. Mais dans quelques dialectes, c'est l'inverse. Votre exemple pourrait donner un sens de toute façon, mais je soupçonne que vous avez l'un des dialectes où? est un littéral et \? est le symbole facultatif. Donc, votre regex signifie probablement "trois chiffres, éventuellement suivis d'un espace ou d'un tableau de bord, suivi de quatre chiffres".

(Un autre indice peut être vu dans des constructions comme\{3 \}, qui est clairement destinée à signifier "exactement 3 de l'élément précédent". Dans la plupart des dialectes de regex, cela serait écrit {3}, et\{serait une attelle littérale .)

8
Ross Smith

Ceci est un résumé rapide des informations qui sont déjà contenues dans les autres réponses.

Dans grep, ? correspond à un caractère de marque littérale et \? indique zéro ou une occurrence de tout ce qui précède. Donc, dans l'exemple de votre question, [ -]\? correspond à un espace ou à un trait d'union, ou rien.

Dans egrep ou grep -E, C'est l'inverse; \? correspond à un point d'interrogation littéral et ? dénote zéro ou une occurrence.

Ceci s'applique à GNU grep; les détails des implémentations non-GNU GREP peuvent différer légèrement. En particulier, grep et egrep étaient historiquement deux programmes distincts et Je ne pense pas que le vieille greps avait le -E option. POSIX spécifie grep -E, mais (j'ai été surpris de découvrir) ne mentionne pas egrep.

6
Keith Thompson