Estoy aprendiendo Linux, y tengo un desafío que parece que no puedo resolver por mi cuenta. Aquí está:
grep una línea de un archivo que contiene 4 números seguidos pero no más de 4.
No estoy seguro de cómo abordar esto. Puedo buscar números específicos pero no su cantidad en una cadena.
1234a12345
mostrarse una línea como , o no?\b\d{4}\b
Respuestas:
Hay dos formas de interpretar esta pregunta; Abordaré ambos casos. Es posible que desee mostrar líneas:
Por ejemplo, (1) se mostraría
1234a56789
, pero (2) no.Si desea mostrar todas las líneas que contienen una secuencia de cuatro dígitos que no es parte de una secuencia de dígitos más larga, una forma es:
Esto utiliza expresiones regulares de Perl , que son compatibles con Ubuntu
grep
( GNU grep )-P
. No coincidirá con el texto como12345
, ni coincidirá con el1234
o2345
que son parte de él. Pero va a coincidir con el1234
de1234a56789
.En expresiones regulares de Perl:
\d
significa cualquier dígito (es una forma corta de decir[0-9]
o[[:digit:]]
).x{4}
coincidex
4 veces. (la{
}
sintaxis no es específica de las expresiones regulares de Perl; también está en expresiones regulares extendidas a través degrep -E
). Así\d{4}
es lo mismo que\d\d\d\d
.(?<!\d)
es una afirmación negativa de ancho cero. Significa "a menos que sea precedido por\d
".(?!\d)
es una afirmación negativa anticipada de ancho cero. Significa "a menos que sea seguido por\d
".(?<!\d)
y(?!\d)
no coincide con el texto fuera de la secuencia de cuatro dígitos; en cambio, (cuando se usan juntos) evitarán que una secuencia de cuatro dígitos coincida si es parte de una secuencia más larga de dígitos.Usar solo el mirar hacia atrás o solo mirar hacia adelante es insuficiente porque la subsecuencia de cuatro dígitos más a la derecha o más a la izquierda aún coincidiría.
Una ventaja de usar las afirmaciones de mirar hacia atrás y mirar hacia adelante es que su patrón solo coincide con las secuencias de cuatro dígitos, y no con el texto circundante. Esto es útil cuando se utiliza el resaltado de color (con la
--color
opción).Por defecto en Ubuntu, cada usuario tiene
alias grep='grep --color=auto'
en su~.bashrc
archivo . Por lo tanto, obtiene el resaltado de color automáticamente cuando ejecuta un comando simple que comienza congrep
(esto es cuando se expanden los alias ) y la salida estándar es un terminal (esto es lo que se verifica). Las coincidencias generalmente se resaltan en un tono rojo (cerca de bermellón ), pero lo he mostrado en negrita en cursiva. Aquí hay una captura de pantalla:--color=auto
E incluso puede
grep
imprimir solo texto coincidente, y no toda la línea, con-o
:De forma alternativa, sin afirmaciones de mirar atrás y mirar atrás
Sin embargo, si usted:
grep
que no sea compatible-P
o no quiera usar una expresión regular de Perl, y... entonces puede lograr esto con una expresión regular extendida en su lugar:
Esto coincide con cuatro dígitos y el carácter sin dígitos, o el principio o el final de la línea, que los rodea. Específicamente:
[0-9]
coincide con cualquier dígito (como[[:digit:]]
, o\d
en expresiones regulares de Perl) y{4}
significa "cuatro veces". Entonces[0-9]{4}
coincide con una secuencia de cuatro dígitos.[^0-9]
coincide con caracteres que no están en el rango de0
hasta9
. Es equivalente a[^[:digit:]]
(o\D
, en expresiones regulares de Perl).^
, cuando no aparece entre[
]
paréntesis, coincide con el comienzo de una línea. Del mismo modo,$
coincide con el final de una línea.|
medios o y paréntesis son para agrupar (como en álgebra). Por lo tanto,(^|[^0-9])
coincide con el comienzo de la línea o un carácter sin dígitos, mientras que($|[^0-9])
coincide con el final de la línea o con un carácter sin dígitos.Entonces, las coincidencias ocurren solo en líneas que contienen una secuencia de cuatro dígitos (
[0-9]{4}
) que es simultáneamente:(^|[^0-9])
), y($|[^0-9])
).Si, por otro lado, desea mostrar todas las líneas que contienen una secuencia de cuatro dígitos, pero no contiene ninguna secuencia de más de cuatro dígitos (incluso una que esté separada de otra secuencia de solo cuatro dígitos), entonces conceptualmente su El objetivo es encontrar líneas que coincidan con un patrón pero no con otro.
Por lo tanto, incluso si sabe cómo hacerlo con un solo patrón, le sugiero que use algo como la segunda sugerencia de
grep
Matt , para los dos patrones por separado.Al hacerlo, no se beneficia mucho de ninguna de las características avanzadas de las expresiones regulares de Perl, por lo que es posible que prefiera no usarlas. Pero de acuerdo con el estilo anterior, aquí hay una reducción de la solución de Matt usando
\d
(y llaves) en lugar de[0-9]
:Como utiliza
[0-9]
, Matt's es más portátil: funcionará en sistemas dondegrep
no admite expresiones regulares de Perl. Si usa[0-9]
(o[[:digit:]]
) en lugar de\d
, pero continúa usándolo{
}
, obtendrá la portabilidad de Matt's de manera un poco más concisa:De forma alternativa, con un solo patrón
Si realmente prefieres un
grep
comando quegrep
s separadas por una tubería , como se indicó anteriormente)... entonces puedes usar:
El
-x
indicador hace que segrep
muestren solo las líneas donde coincide la línea completa (en lugar de cualquier línea que contiene una coincidencia).He usado una expresión regular de Perl porque creo que la brevedad
\d
y la\D
claridad sustancialmente aumentan en este caso. Pero si necesita algo portátil para sistemas dondegrep
no es compatible-P
, puede reemplazarlos con[0-9]
y[^0-9]
(o con[[:digit:]]
y[^[:digit]]
):La forma en que funcionan estas expresiones regulares es:
En el medio,
\d{4}
o[0-9]{4}
coincide con una secuencia de cuatro dígitos. Es posible que tengamos más de uno de estos, pero necesitamos tener al menos uno.A la izquierda,
(\d{0,4}\D)*
o([0-9]{0,4}[^0-9])*
coincide con cero o más (*
) instancias de no más de cuatro dígitos seguidos de un no dígito. Cero dígitos (es decir, nada) es una posibilidad para "no más de cuatro dígitos". Esto coincide con (a) la cadena vacía o (b) cualquier cadena que termine en un no dígito y que no contenga ninguna secuencia de más de cuatro dígitos.Dado que el texto inmediatamente a la izquierda de la central
\d{4}
(o[0-9]{4}
) debe estar vacío o terminar con un no dígito, esto evita que la central\d{4}
coincida con cuatro dígitos que tienen otro (quinto) dígito justo a la izquierda de ellos.A la derecha,
(\D\d{0,4})*
o([^0-9][0-9]{0,4})*
coincide con cero o más (*
) instancias de un no dígito seguido de no más de cuatro dígitos (que, como antes, podrían ser cuatro, tres, dos, uno o incluso ninguno). Esto coincide con (a) la cadena vacía o (b) cualquier cadena que comience en un no dígito y que no contenga ninguna secuencia de más de cuatro dígitos.Dado que el texto inmediatamente a la derecha de la central
\d{4}
(o[0-9]{4}
) debe estar vacío o comenzar con un no dígito, esto evita que la central\d{4}
coincida con cuatro dígitos que tienen otro (quinto) dígito justo a la derecha de ellos.Esto asegura que una secuencia de cuatro dígitos esté presente en alguna parte, y que ninguna secuencia de cinco o más dígitos esté presente en ninguna parte.
No está mal ni está mal hacerlo de esta manera. Pero quizás la razón más importante para considerar esta alternativa es que aclara el beneficio de usar (o similar) en su lugar, como se sugirió anteriormente y en la respuesta de Matt .
grep -P '\d{4}' file | grep -Pv '\d{5}'
De esa manera, queda claro que su objetivo es seleccionar líneas que contengan una cosa pero no otra. Además, la sintaxis es más simple (por lo que muchos lectores / mantenedores pueden entenderla más rápidamente).
fuente
Esto le mostrará 4 números seguidos pero no más.
Tenga en cuenta que ^ significa no
Hay un problema con esto, aunque no estoy seguro de cómo solucionarlo ... si el número es el final de la línea, entonces no aparecerá.
Sin embargo, esta versión más fea funcionaría para ese caso
fuente
a12345b
, porque coincide2345b
.Si
grep
no admite expresiones regulares perl (-P
), use el siguiente comando de shell:donde
printf '[0-9]%.0s' {1..4}
producirá 4 veces[0-9]
. Este método es útil cuando tiene dígitos largos y no desea repetir el patrón (simplemente reemplace4
con su número de dígitos para buscar).El uso
-w
buscará las palabras completas. Sin embargo, si está interesado en cadenas alfanuméricas, como1234a
, agregue[^0-9]
al final del patrón, por ejemploUsar
$()
es básicamente una sustitución de comando . Mira esta publicación para ver cómo seprintf
repite el patrón.fuente
Puede probar el siguiente comando reemplazándolo
file
con el nombre real del archivo en su sistema:También puede consultar este tutorial para más usos del comando grep.
fuente