texto script para lineas leer fichero extraer entre diferencia comparar como comando archivos archivo agregar bash file-io set-difference

script - Bash, Linux: establece la diferencia entre dos archivos de texto



diferencia entre shell y bash (5)

Alguien me mostró cómo hacer exactamente esto hace un par de meses, y luego no pude encontrarlo por un tiempo ... y mientras miraba tropecé con tu pregunta. Aquí está :

set_union () { sort $1 $2 | uniq } set_difference () { sort $1 $2 $2 | uniq -u } set_symmetric_difference() { sort $1 $2 | uniq -u }

Tengo dos archivos A - nodes_to_delete y B - nodes_to_keep . Cada archivo tiene muchas líneas con identificadores numéricos.

Quiero tener la lista de identificadores numéricos que están en nodes_to_delete pero NO en nodes_to_keep , por ejemplo, alt text http://mathworld.wolfram.com/images/equations/SetDifference/Inline1.gif .

Hacerlo dentro de una base de datos PostgreSQL es irrazonablemente lento. ¿Alguna forma ordenada de hacerlo en bash usando las herramientas CLI de Linux?

ACTUALIZACIÓN: Esto parece ser un trabajo Pythonic, pero los archivos son realmente, muy grandes. He resuelto algunos problemas similares usando uniq , sort y algunas técnicas de teoría de conjuntos. Esto fue aproximadamente dos o tres órdenes de magnitud más rápido que los equivalentes de la base de datos.


El comando comm hace eso.


Tal vez necesites una mejor manera de hacerlo en Postgres, puedo apostar que no encontrarás una forma más rápida de hacerlo con archivos planos. Debería poder realizar una unión interna simple y asumir que ambos id cols están indexados, lo que debería ser muy rápido.


use comm - comparará dos archivos ordenados línea por línea

La respuesta a la pregunta de OP usando esta configuración de ejemplo aparece a continuación. Este comando devolverá líneas exclusivas para deleteNodes, no en keepNodes

comm -1 -3 <(sort keepNodes) <(sort deleteNodes)

explicación: mostrar líneas únicas para deleteNodes, ocultar otras líneas

configuración de ejemplo

Usaremos keepNodes y deleteNodes. Se usan como entrada sin clasificar.

$ cat > keepNodes <(echo bob; echo amber;) $ cat > deleteNodes <(echo bob; echo ann;)

Por defecto, sin argumentos, comm imprime 3 columnas

unique_to_FILE1 unique_to_FILE2 lines_appear_in_both

Este es un ejemplo básico de comm sin argumentos. Tenga en cuenta las tres columnas.

$ comm <(sort keepNodes) <(sort deleteNodes) amber ann bob

Suprimir la salida de la columna

Suprima la columna 1, 2 o 3 con -N; tenga en cuenta que cuando una columna está oculta, el espacio en blanco se encoge.

$ comm -1 <(sort keepNodes) <(sort deleteNodes) ann bob $ comm -2 <(sort keepNodes) <(sort deleteNodes) amber bob $ comm -3 <(sort keepNodes) <(sort deleteNodes) amber ann $ comm -1 -3 <(sort keepNodes) <(sort deleteNodes) ann $ comm -2 -3 <(sort keepNodes) <(sort deleteNodes) amber $ comm -1 -2 <(sort keepNodes) <(sort deleteNodes) bob

Fallará con gracia cuando olvide clasificar

comm: file 1 is not in sorted order


comm fue diseñado específicamente para este tipo de caso de uso, pero requiere una entrada ordenada.

awk es posiblemente una mejor herramienta para esto, ya que es bastante sencillo encontrar la diferencia establecida, no requiere sort y ofrece flexibilidad adicional.

awk ''NR == FNR { a[$0]; next } !($0 in a)'' nodes_to_keep nodes_to_delete

Tal vez, por ejemplo, desee encontrar solo la diferencia en las líneas que representan números no negativos:

awk -v r=''^[0-9]+$'' ''NR == FNR && $0 ~ r { a[$0] next } $0 ~ r && !($0 in a)'' nodes_to_keep nodes_to_delete