Cómo hacer anti-unión o unión inversa en bash

Quiero realizar lo que algunos software de análisis de datos llaman anti-unión: eliminar de una lista esas líneas líneas coincidentes en otra lista. Aquí hay algunos datos de juguetes y el resultado esperado:

$ echo -e "a\nb\nc\nd" > list1 $ echo -e "c\nd\ne\nf" > list2 $ antijoincommand list1 list2 a b 

Comentarios

Respuesta

No usaría join para esto porque join requiere que se ordenen las entradas, lo cual es una complicación innecesaria para un trabajo tan simple. En su lugar, podría usar grep:

$ grep -vxFf list2 list1 a b 

O awk:

$ awk "NR==FNR{++a[$0]} !a[$0]" list2 list1 a b 

Si los archivos ya están ordenados, una alternativa a join -v 1 sería comm -23

$ comm -23 list1 list2 a b 

Comentarios

  • Evitar sort con grep es genial por los datos de juguetes que proporcioné. ¡Gracias! En el mundo real, mi archivo1 a menudo tiene varias columnas de datos, una de las cuales se usa para la combinación. Una versión modificada de tu awk el código abordaría este caso de uso.
  • @Josh sí, simplemente cambie $0 por $N donde N es el número de campo al que se está uniendo.
  • Esto funciona incluso si los números de columna en file1 y file2 son diferentes: como awk ' NR == FNR {++ a [$ 2]}! a [$ 5] ' list2 list1; Es bastante habitual que el archivo de etiquetas tenga un formato diferente al de los datos principales.

Respuesta

Una forma de hacer esto con la utilidad join es:

$ join -v 1 list1 list2 a b 

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *