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 \?
?
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 \?
?
Respuestas:
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 grep
utilizaba 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 -E
opció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:
grep -E
es la forma oficial POSIX. egrep
fue desaprobado en susv2 (1997) y eliminado en susv3 (2001) de las especificaciones POSIX y Unix.
\?
es un GNUism sin embargo.
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 .)
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 egrep
o 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, grep
e egrep
históricamente eran dos programas separados, y no creo que los viejos grep
tuvieran la -E
opción. POSIX especifica grep -E
, pero (me sorprendió descubrir) no menciona egrep
.
egrep
comando es equivalente agrep -E
. Para versiones distintas de GNU grep,grep
podría o no aceptar la-E
opción, yegrep
podría ser un programa separado.