Que hace \? significa en una expresión regular?

16

El siguiente comando se utiliza para buscar un número de teléfono de 7 dígitos:

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

¿Qué significa \??

usuario5997
fuente

Respuestas:

21

Es como ?en muchos otros motores de expresión regular, y significa "coincidencia cero o uno de lo que haya antes".

En su ejemplo, \?se aplica a [ -], lo que significa que intenta hacer coincidir un espacio o un signo menos, pero que el espacio o el signo menos es opcional.

Entonces, cualquiera de estos coincidirá:

555 1234
555-1234
5551234

La razón por la que se escribe en \?lugar de hacerlo ?es por la compatibilidad con versiones anteriores.

La versión original de greputilizaba un tipo diferente de expresión regular llamada "expresión regular básica" donde ?solo significaba un signo de interrogación literal.

Para que GNU grep pudiera tener la funcionalidad cero o una, la agregaron, pero tuvieron que usar la \?sintaxis para que los scripts que se usaban ?funcionaran como se esperaba.

Tenga en cuenta que grep tiene una -Eopción que hace que use el tipo más común de expresión regular, llamada "expresiones regulares extendidas".

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

Informacion adicional:

Mikel
fuente
El egrepcomando es equivalente a grep -E. Para versiones distintas de GNU grep, greppodría o no aceptar la -Eopción, y egreppodría ser un programa separado.
Keith Thompson, el
@KeithThompson, grep -Ees la forma oficial POSIX. egrepfue desaprobado en susv2 (1997) y eliminado en susv3 (2001) de las especificaciones POSIX y Unix.
Stéphane Chazelas
1
\?es un GNUism sin embargo.
Stéphane Chazelas
8

Desafortunadamente, la sintaxis exacta de las expresiones regulares varía ligeramente entre los diferentes programas: las expresiones regulares grep no son exactamente las mismas que las expresiones regulares sed, que no son exactamente las mismas que las expresiones regulares Emacs, que no son exactamente las mismas expresiones regulares de C ++, y así en. Para empeorar las cosas, incluso una herramienta "estándar" como grep puede variar ligeramente entre diferentes sistemas operativos tipo Unix.

En una expresión regular, algunos caracteres tienen un significado especial (como los corchetes en su ejemplo) y vuelven a su significado normal como caracteres literales cuando los "escapa" colocando una barra invertida delante de ellos (por lo que un corchete literal sería Escrito como \[). Otros trabajan al revés, y solo adquieren un significado especial cuando se escapan (por ejemplo, simple n es solo una letra, pero \ n es un avance de línea). Y estos, nuevamente, pueden variar entre implementaciones de expresiones regulares.

En la mayoría de las implementaciones de expresiones regulares, un signo de interrogación significa que el elemento anterior es opcional, mientras que un signo de interrogación escapado (\?) Es un signo de interrogación literal. Pero en algunos dialectos, es al revés. Su ejemplo podría tener sentido en ambos sentidos, pero sospecho que tiene uno de los dialectos ¿dónde? es un literal y \? Es el símbolo opcional. Por lo tanto, su expresión regular probablemente significa "tres dígitos, opcionalmente seguidos de un espacio o guión, seguido de cuatro dígitos".

(Se puede ver otra pista en construcciones como \ {3 \}, que claramente significa "exactamente 3 del elemento anterior". En la mayoría de los dialectos de expresiones regulares, esto se escribiría {3}, y \ {sería una llave literal .)

Ross Smith
fuente
6

Este es un resumen rápido de la información que ya figura en las otras respuestas.

En grep, ?coincide con un carácter de signo de interrogación literal y \?denota cero o una ocurrencia de lo que sea que lo precede. Entonces, en el ejemplo de su pregunta, [ -]\?coincide con un espacio, un guión o nada.

En egrepo grep -E, es al revés; \?coincide con un signo de interrogación literal y ?denota cero o una ocurrencia.

Esto se aplica a GNU grep; Los detalles para las implementaciones grep que no son GNU pueden diferir ligeramente. En particular, grepe egrephistóricamente eran dos programas separados, y no creo que los viejos greptuvieran la -Eopción. POSIX especifica grep -E, pero (me sorprendió descubrir) no menciona egrep.

Keith Thompson
fuente