Estoy tratando de entender qué expresiones (^[0-9]..[a-zA-Z ]+$)
detecta exactamente la expresión regular en grep
el comando (terminal de Linux)
Lo sé si escribiera el siguiente comando:
grep ^[0-9]..[a-zA-Z] filename.txt
Detectaré cualquier línea que contenga expresiones como 92afg
Pero no estoy seguro de cuál +$
significa ni qué tipo de expresiones podré detectar con el comando
grep ^[0-9]..[a-zA-Z]+$ filename.txt
Intenté abrir un nuevo archivo de texto y simplemente escribir expresiones que pensé que se detectarían, pero ninguna coincidía, así que agradecería una explicación para esto.
Respuesta1
Analicémoslo. En primer lugar, tenga en cuenta que esta RegExp utiliza el"Expresión regular extendida"sintaxis (ERE): +
es un metacarácter que no funciona en la sintaxis de "expresión regular básica" que grep
se usa de forma predeterminada (lo que significa que coincidiría consigo mismo y requeriría un literal +
en esa posición), por lo que si desea usar esa expresión regular con grep
, deberá pasar la -E
opción.
- Es
^
un ancla que une esta posición de la expresión regular al inicio de la línea. - Es
[0-9]
una lista de caracteres y coincidirá con cualquier (1) carácter que se encuentre en el rango de clasificación entre0
y9
. Lo que eso comprende exactamente depende del "orden de clasificación", determinado entre otros por la variable de entornoLC_COLLATE
. - Coincide
.
con cualquier carácter, por lo que dos..
significa "dos caracteres cualesquiera". - La
[a-zA-Z]
parte posterior es una lista de caracteres y coincidirá con los caracteres (1) que se encuentran entrea
yz
y, además, con los que se encuentran entreA
yZ
. Nuevamente, ¡lo que eso significa depende del orden de clasificación! - El
+
significa "uno o más de los anteriores" - Es
$
un ancla que une esta posición de la expresión regular al final de la línea.
Entonces, tu RegExse pretende(1) haga coincidir cualquier línea que
- empezar con cualquier dígito
- seguido de dos caracteres cualesquiera
- y solo contiene letras (pero al menos una) hasta el final de la línea.
(1) para conocer lo que realmente podría hacer, consulte a continuación
Algunas notas
En su ejemplo, utiliza la expresión regular sin comillas. Eso significa que todos los caracteres están abiertos a la interpretación del shell antes de pasarlos al
grep
comando. Si su patrón contiene$
caracteres globales (*
¡?
y[...]
listas de caracteres!), el shell puede intentar realizar una expansión variable (reemplazando así partes de su RegEx) o expandir patrones globales en posiblemente varios nombres de archivos, de modo que al final tenga más argumentos. en la línea de comando que originalmente pretendías. Otros caracteres que son especiales del shell (>
,#
y;
similares) pueden provocar comportamientos aún más inesperados. Deberías usargrep -E '^[0-9]..[a-zA-Z]+$' filename.txt
en cambio. Tenga en cuenta que puede deshacerse de los anclajes de apertura y cierre utilizando la
-x
bandera para imponer la coincidencia de "línea completa":grep -x -E '[0-9]..[a-zA-Z]+' filename.txt
Las listas de caracteres que contienen rangos (como
a-z
) sonpeligrosoporque es posible que no te den lo que piensas. Ingenuamente se podría esperar que coincidan con todos los caracteres que se encuentran entre el carácter inicial y final de la tabla ASCII, pero eso sólo es cierto para laC
configuración regional. En otras configuraciones regionales (y en particular en las configuraciones regionales del sistema generalmente configuradas, comoen_US.UTF-8
), el orden de clasificación es algo asíaAbB ... zZ
como quea-z
también coincidiría con la mayoría de las letras mayúsculas. Además, la coincidencia en realidad no se realiza en el nivel de caracteres individuales sino en "elementos de intercalación", lo que significa en algunas regiones, inclusocombinaciones de varias letraspuede coincidir (por ejemplo,dzs
en húngaro)! Veresta respuesta(o, en general, la mayoría de las respuestas de @Stéphane Chazelas sobre la coincidencia de patrones) para obtener más información. Si desea asegurarse de que sus rangos funcionen, establezca el orden de clasificación al menos para el comando dado a través deLC_COLLATE="C" grep -E ' ... ' filename.txt
Respuesta2
+
significa "una o más repeticiones del anterior", $
es "fin de línea". Tenga en cuenta la diferencia versus *
con significa "cero o más repeticiones".
Básicamente significa: cualquier línea que comience con un dígito, seguida de dos caracteres de cualquier tipo y posteriormente una o más letras (posiblemente mayúsculas)¹ hasta el final de la línea.
(¹ tenga cuidado, es posible que algunas configuraciones regionales no solo tengan las 26 letras que esperaría en AZ o az, por ejemplo, è
o ŷ
según el idioma)
Para obtener una buena guía sobre expresiones regulares, recomiendo encarecidamenteEl hermoso sitio web de Grimorio., que también recomiendo de todo corazón, por ejemplo, sed
y awk
.
¿Por qué no coincide?
+
es parte de las expresiones regulares extendidas (y de lo contrario se interpreta como un +
signo literal).
Entonces, para usarlo +
como "una o más repeticiones", use el -E
indicador -y grep
también componga la expresión regular para evitar problemas con los caracteres especiales del shell:
grep -E '^[0-9]..[a-zA-Z]+$' filename.txt