A y expresiones con grep necesita dos invocaciones:
grep -Ei "search term" | grep -Eiv "exclude term"
Si los términos que busca no son expresiones regulares, utilice la coincidencia de cadenas fijas (-F
) que es más rápido:
grep -F "search term" | grep -Fv "exclude term"
Aparte de invocar grep dos veces, solo se me ocurre una forma de lograrlo. Se trata de Expresiones Regulares Compatibles con Perl (PCRE) y algunas aserciones de búsqueda bastante complicadas.
Para buscar foo excluyendo coincidencias que contienen barra , puedes usar:
grep -P '(?=^((?!bar).)*$)foo'
Así es como funciona:
-
(?!bar)
coincide con cualquier cosa que no sea bar sin consumir caracteres de la cadena. Entonces.
consume un solo carácter. -
^((?!bar).)*
repite lo anterior desde el principio de la cadena (^
) hasta el final ($
). Fallará sibar
se encuentra en cualquier punto dado, desde(?!bar)
no coincidirá. -
(?=^((?!bar).)*$)
se asegura de que la cadena coincida con el patrón anterior, sin consumir caracteres de la cadena. -
foo
busca foo como de costumbre.
Encontré este truco en la expresión regular para hacer coincidir la cadena que no contiene una palabra. En la respuesta de Bart Kiers, puede encontrar una explicación mucho más detallada de cómo funciona la anticipación negativa.
Si quiere hacer esto de una vez, puede usar awk en lugar de grep.
Formato:
echo "some text" | awk '/pattern to match/ && !/pattern to exclude/'
Ejemplos:
echo "hello there" | awk '/hello/ && !/there/'
No devuelve nada.
echo "hello thre" | awk '/hello/ && !/there/'
Devoluciones:hola tres
echo "hllo there" | awk '/hello/ && !/there/'
No devuelve nada.
Para patrones múltiples, puede usar paréntesis para agruparlos.
Ejemplos:
echo "hello thre" | awk '(/hello/ || /hi/) && !/there/'
Devoluciones:hola tres
echo "hi thre" | awk '(/hello/ || /hi/) && !/there/'
Devoluciones:hola thre
echo "hello there" | awk '(/hello/ || /hi/) && !/there/'
No devuelve nada.
echo "hi there" | awk '(/hello/ || /hi/) && !/there/'
No devuelve nada.