Con grep
implementaciones que admiten expresiones regulares tipo perl (like pcregrep
o GNU o ast-open grep -P
), puede hacerlo en una grep
invocación con:
grep -P '^(?=.*pat1)(?!.*pat2)|^(?=.*pat2)(?!.*pat1)'
Es decir, encontrar las líneas que coinciden pat1
pero no pat2
, o pat2
no pat1
.
(?=...)
y (?!...)
son respectivamente operadores de anticipación y de anticipación negativos. Entonces, técnicamente, lo anterior busca el comienzo del sujeto ( ^
) siempre que sea seguido .*pat1
y no seguido .*pat2
, o lo mismo con pat1
e pat2
invertido.
Eso es subóptimo para las líneas que contienen ambos patrones, ya que luego se buscarían dos veces. En su lugar, podría usar operadores perl más avanzados como:
grep -P '^(?=.*pat1|())(?(1)(?=.*pat2)|(?!.*pat2))'
(?(1)yespattern|nopattern)
coincide con yespattern
si el grupo de captura 1
st (vacío ()
arriba) coincide, y de lo nopattern
contrario. Si esa ()
partidos, eso significa que pat1
no coinciden, por lo que buscamos pat2
(aspecto positivo por delante), y buscamos no pat2
de otro modo (por delante aspecto negativo).
Con sed
, podrías escribirlo:
sed -ne '/pat1/{/pat2/!p;d;}' -e '/pat2/p'
[a-z][a-z0-9]\(,7\}\(\.[a-z0-9]\{,3\}\)+
? (2) ¿Qué sucede si una de las palabras / patrones aparece más de una vez en una línea (y la otra no aparece)? ¿Es eso equivalente a la palabra que aparece una vez, o cuenta como ocurrencias múltiples?