Estoy tratando de usar greppara mostrar solo las líneas que contienen cualquiera de las dos palabras, si solo una de ellas aparece en la línea, pero no si están en la misma línea.
Hasta ahora lo he intentado grep pattern1 | grep pattern2 | ...pero no obtuve el resultado que esperaba.

[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?Respuestas:
Una herramienta que no
grepsea el camino a seguir.Usando perl, por ejemplo, el comando sería:
perl -neejecuta el comando dado sobre cada línea de stdin, que en este caso imprime la línea si coincide/pattern1/ xor /pattern2/o, en otras palabras, coincide con un patrón pero no con el otro (exclusivo o).Esto funciona para el patrón en cualquier orden, y debería tener un mejor rendimiento que las invocaciones múltiples de
grep, y también es menos tipeado.O, incluso más corto, con awk:
o para versiones de awk que no tienen
xor:fuente
xordisponible solo en GNU Awk?/pattern1/+/pattern2/==1irxorfalta.\b) en los patrones mismos, es decir\bword\b.Con GNU
grep, puede pasar ambas palabrasgrepy luego eliminar las líneas que contienen ambos patrones.fuente
Probar con
egrepfuente
grep -e foo -e bar | grep -v -e 'foo.*bar' -e 'bar.*foo'Direct invocation as either egrep or fgrep is deprecated- prefierogrep -E-fy-eopciones, aunque las más antiguasegrepyfgrepcontinuarán siendo compatibles durante un tiempo.grep(que soporta-F,-E,-e,-fcomo requiere POSIX) está en/usr/xpg4/bin. Las utilidades en/binson anticuadas.Con
grepimplementaciones que admiten expresiones regulares tipo perl (likepcregrepo GNU o ast-opengrep -P), puede hacerlo en unagrepinvocación con:Es decir, encontrar las líneas que coinciden
pat1pero nopat2, opat2nopat1.(?=...)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.*pat1y no seguido.*pat2, o lo mismo conpat1epat2invertido.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:
(?(1)yespattern|nopattern)coincide conyespatternsi el grupo de captura1st (vacío()arriba) coincide, y de lonopatterncontrario. Si esa()partidos, eso significa quepat1no coinciden, por lo que buscamospat2(aspecto positivo por delante), y buscamos nopat2de otro modo (por delante aspecto negativo).Con
sed, podrías escribirlo:fuente
grep: the -P option only supports a single pattern, al menos en todos los sistemas a los que tengo acceso. Sin embargo, +1 para tu segunda solución.grep.pcregrepy grep ast-open no tienen ese problema. He reemplazado el múltiplo-econ el operador de alternancia RE, por lo que ahora debería funcionar con GNUgreptambién.En términos booleanos, está buscando A xor B, que se puede escribir como
(A y no B)
o
(B y no A)
Dado que su pregunta no menciona que le preocupa el orden de la salida siempre que se muestren las líneas coincidentes, la expansión booleana de A xor B es bastante simple en grep:
fuente
sort | uniq.Para el siguiente ejemplo:
Esto se puede hacer simplemente con
grep -E,uniqywc.Si
grepse compila con expresiones regulares de Perl, puede coincidir en la última aparición en lugar de necesitar canalizar auniq:Salida del resultado:
Una frase:
Si no desea codificar el patrón, ensamblarlo con un conjunto variable de elementos puede automatizarse con una función.
Esto también se puede hacer de forma nativa en Bash como una función sin canalizaciones o procesos adicionales, pero sería más complicado y probablemente esté fuera del alcance de su pregunta.
fuente
Big apple\nypear-shaped\n, entonces la salida debe contener ambas líneas. Su solución obtendría una cuenta de 2; la versión larga informaría "Ambas palabras coinciden" (que es una respuesta a la pregunta incorrecta) y la versión corta no diría nada en absoluto. (3) Una sugerencia: usar-oaquí es una muy mala idea, ya que oculta las líneas que contienen las coincidencias, por lo que no puede ver cuándo ambas palabras aparecen en la misma línea. ... (Continúa)uniq/sort -uy la elegante expresión regular de Perl para que coincida solo con la última aparición en cada línea realmente no se suman a una respuesta útil a esta pregunta. Pero, incluso si lo hicieran, sería una mala respuesta porque no explicas cómo contribuyen a responder la pregunta. (Ver la respuesta de Stéphane Chazelas para un ejemplo de una buena explicación.)