"Desagrupar": qué patrones no coinciden


13

Estoy buscando un comando o script para hacer lo siguiente, dado:

file1.txt:

abcd
efgh 
ijkl
mnop

file2.txt:

123abcd123
123efgh123
123mnop123

Quiero un comando que haga algo como esto:

ungrep file1.txt file2.txt

y devuelve lo siguiente:

ijkl

En otras palabras, me está dando las líneas en file1.txt que no devolverán ningún resultado en un grep de file2.txt. Sé que puedo hacer esto iterando a través de file1.txt, grepping file2.txt para cada línea y almacenando el resultado, y generando cualquier línea donde el resultado esté vacío, pero esperaba una forma más eficiente de hacerlo.

Respuestas:


18

Con GNU greplo siguiente debería funcionar. Usando la -fopción, pasar file1.txtcomo un "archivo de patrones", pero también pasarlo por segunda vez como un archivo de datos. Use -opara informar solo las partes coincidentes. Finalmente, extrae las palabras que coinciden solo una vez; corresponden a las líneas de las file1.txtque no se encuentran coincidencias file2.txt.

grep -h -o -f  file1.txt file2.txt file1.txt | sort | uniq -u
ijkl

Muy buena descripcion. Gracias y +1.
— unxnut

44
Podría lograr el mismo efecto sin el truco grep: sort file1.txt <(grep -of file1.txt file2.txt) | uniq -upero, como su solución, esto solo funciona cuando el archivo de patrones no contiene metacaracteres regex.
— rici

@rici, ese es un muy buen punto
— iruvar

2
Mejora:grep -oFf file1.txt file2.txt | sort file1.txt - | uniq -u
— Stéphane Chazelas

10

Podrías hacerlo con awk:

awk '
  NR == FNR {w[$0]; next}
  {for (i in w) if (index($0,i)) delete w[i]}
  END {for (i in w) print i}' file1.txt file2.txt

Al usar index, buscamos subcadenas en lugar de hacer coincidir expresiones regulares.

Como eliminamos la palabra de la matriz tan pronto como encontramos una coincidencia, evitamos búsquedas innecesarias.


1
Solo aceptaría este. No invoca ninguna clasificación O (n log n), y no falla de manera extraña cuando los patrones contienen metacaracteres regex, y podría extenderse para admitir expresiones regulares.
— Kaz

No puedo creer que simplemente evaluar w[$0]tenga el efecto secundario de agregar la clave a la matriz.
— Kaz

1
@Kaz, sí, eso puede ser confuso, y encuentra muchas secuencias de comandos que no asignan intencionalmente elementos de la matriz de forma involuntaria al hacerlo en if (a[$1])lugar de, if ($1 in a)por ejemplo. Es el caso de cada uno awkincluyendo el original awky nawk, pero mirando el estándar de ayer, no pude encontrarlo especificado.
— Stéphane Chazelas

1
@Kaz Aquí está la cita POSIX: "La aplicación se asegurará de que un índice multidimensional utilizado con el operador in esté entre paréntesis. El operador in , que prueba la existencia de un elemento de matriz particular, no hará que ese elemento exista. otra referencia a un elemento de matriz inexistente lo creará automáticamente ". Se puede encontrar desplazándose uno o dos párrafos hacia arriba desde aquí .
— jw013

1
Siempre y cuando file1no sea enorme (por algún valor de enorme), preferiría esta solución, ya que no requiere ningún tipo de clasificación file2y se espera que sea mucho más eficiente.
— jw013
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.