Estoy intentando grep para todas las instancias de Ui\.
no seguido Line
o incluso solo de la letraL
¿Cuál es la forma correcta de escribir una expresión regular para encontrar todas las instancias de una cadena en particular NO seguida de otra cadena?
Usando lookaheads
grep "Ui\.(?!L)" *
bash: !L: event not found
grep "Ui\.(?!(Line))" *
nothing
regex
grep
regex-lookarounds
Lee Quarella
fuente
fuente
set +o histexpand
en Bash oset +H
YMMV.Respuestas:
La búsqueda anticipada negativa, que es lo que busca, requiere una herramienta más poderosa que la estándar
grep
. Necesita un grep habilitado para PCRE.Si tiene GNU
grep
, la versión actual admite opciones-P
o--perl-regexp
y luego puede usar la expresión regular que desee.Si no tiene (una versión suficientemente reciente de) GNU
grep
, considere obtenerack
.fuente
!
como un carácter especial.-P
no es compatible resultado tuberías volver a intentargrep --invert-match
, por ejemplo:git log --diff-filter=D --summary | grep -E 'delete.*? src' | grep -E --invert-match 'xml'
. Asegúrate de votar la respuesta de @Vinicius Ottoni.La respuesta a parte de su problema está aquí, y ack se comportaría de la misma manera: Ack y búsqueda anticipada negativa dando errores
Está utilizando comillas dobles para grep, lo que permite que bash "interprete
!
como comando de expansión de historial".Necesita envolver su patrón en Citas individuales:
grep 'Ui\.(?!L)' *
Sin embargo, consulte la respuesta de @ JonathanLeffler para abordar los problemas con las búsquedas negativas en estándar
grep
.fuente
grep
con la funcionalidad de estándargrep
, donde el estándar paragrep
es POSIX. Lo que dices también es cierto: ejecuto Bash con los barbarismos de C-shell desactivados (porque si quisiera un shell C, usaría uno, pero no quiero uno), por lo que las!
cosas no me afectan - pero para obtener vistas anticipadas negativas, necesita no estándargrep
.Probablemente no pueda realizar búsquedas estándar negativas usando grep, pero normalmente debería poder obtener un comportamiento equivalente usando el modificador "inverso" '-v'. Con eso, puede construir una expresión regular para el complemento de lo que desea hacer coincidir y luego canalizarlo a través de 2 greps.
Para la expresión regular en cuestión, puede hacer algo como
fuente
Si necesita usar una implementación de expresiones regulares que no admita búsquedas anticipadas negativas y no le importa hacer coincidir caracteres adicionales *, entonces puede usar clases de caracteres negadas
[^L]
, alternancia|
y el final del ancla de cadena$
.En tu caso
grep 'Ui\.\([^L]\|$\)' *
hace el trabajo.Ui\.
coincide con la cadena que le interesa\([^L]\|$\)
coincide con cualquier carácter que no seaL
o coincide con el final de la línea:[^L]
o$
.Si desea excluir más de un carácter, solo necesita agregar más alternancia y negación. Para encontrar
a
no seguido porbc
:grep 'a\(\([^b]\|$\)\|\(b\([^c]\|$\)\)\)' *
Que es (
a
seguido de nob
o seguido del final de la línea:a
entonces[^b]
o$
) o (a
seguido deb
cuál es seguido de noc
o del final de la línea:a
entoncesb
, entonces[^c]
o$
.Este tipo de expresión llega a ser bastante difícil de manejar y propensa a errores incluso con una cadena corta. Podría escribir algo para generar las expresiones por usted, pero probablemente sería más fácil usar una implementación de expresiones regulares que admita búsquedas anticipadas negativas.
* Si su implementación admite grupos que no capturan, puede evitar capturar caracteres adicionales.
fuente
Si su grep no admite -P o --perl-regexp, y puede instalar grep habilitado para PCRE, por ejemplo, "pcregrep", entonces no necesitará ninguna opción de línea de comandos como GNU grep para aceptar Perl-compatible regular expresiones, solo corre
No necesita otro grupo anidado para "Línea" como en su ejemplo "Ui. (?! (Línea))" - el grupo externo es suficiente, como lo he mostrado arriba.
Déjame darte otro ejemplo de aseveraciones negativas: cuando tienes una lista de líneas, devuelta por "ipset", cada línea muestra el número de paquetes en el medio de la línea, y no necesitas líneas con cero paquetes, simplemente correr:
Si le gustan las expresiones regulares compatibles con perl y tiene perl pero no tiene pcregrep o su grep no es compatible con --perl-regexp, puede usar scripts de perl de una línea que funcionen de la misma manera que grep:
Perl acepta stdin de la misma manera que grep, por ejemplo
fuente