"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.

Edward Shtern
fuente

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
iruvar
fuente
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.

Stéphane Chazelas
fuente
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