Diferencia de dos archivos grandes

Diferencia de dos archivos grandes

Tengo "test1.csv" y contiene

200,400,600,800
100,300,500,700
50,25,125,310

y test2.csv y contiene

100,4,2,1,7
200,400,600,800
21,22,23,24,25
50,25,125,310
50,25,700,5

ahora

diff test2.csv test1.csv > result.csv

es diferente que

diff test1.csv test2.csv > result.csv

No sé cuál es el orden correcto pero quiero algo más, los dos comandos anteriores generarán algo como

2 > 100,4,2,1,7
   3 2,3c3,5
   4 < 100,300,500,700
   5 < 50,25,125,310
   6 \ No newline at end of file
   7 ---
   8 > 21,22,23,24,25
   9 > 50,25,125,310

Quiero mostrar solo la diferencia, por lo que results.csv debería verse así

100,300,500,700
100,4,2,1,7
21,22,23,24,25
50,25,700,5

Lo intenté diff -qy diff -sno funcionaron. No importa el orden, lo que importa es que quiero ver solo la diferencia, ni > ni < ni espacios en blanco.

grep -FvFfuncionó en archivos más pequeños, no en los grandes

El primer archivo contiene más de 5 millones de líneas, el segundo archivo contiene 1300.

entonces results.csv debería dar como resultado ~4,998,700 líneas

También probé grep -F -x -v -f lo cual no funcionó.

Respuesta1

Suena como un trabajo para comm:

$ comm -3 <(sort test1.csv) <(sort test2.csv)
100,300,500,700
    100,4,2,1,7
    21,22,23,24,25
    50,25,700,5

Como se explica en man comm:

   -1     suppress column 1 (lines unique to FILE1)

   -2     suppress column 2 (lines unique to FILE2)

   -3     suppress column 3 (lines that appear in both files)

Entonces, esto -3significa que solo se imprimirán las líneas que sean exclusivas de uno de los archivos. Sin embargo, tienen sangría según el archivo en el que se encontraron. Para eliminar la pestaña, utilice:

$ comm -3 <(sort test1.csv) <(sort test2.csv) | tr -d '\t'
100,300,500,700
100,4,2,1,7
21,22,23,24,25
50,25,700,5

En este caso, ni siquiera necesitas ordenar los archivos y puedes simplificar lo anterior para:

comm -3 test1.csv test2.csv | tr -d '\t' > difference.csv

Respuesta2

Usando grepcon bashsustitución de procesos:

$ cat <(grep -vFf test2.csv test1.csv) <(grep -vFf test1.csv test2.csv)
100,300,500,700
100,4,2,1,7
21,22,23,24,25
50,25,700,5

Para guardar la salida como results.csv:

cat <(grep -vFf test2.csv test1.csv) <(grep -vFf test1.csv test2.csv) >results.csv
  • <()es elbashpatrón de sustitución de procesos

  • grep -vFf test2.csv test1.csvencontrará las líneas únicas para solotest1.csv

  • grep -vFf test1.csv test2.csvencontrará las líneas únicas para solotest2.csv

  • Finalmente estamos resumiendo los resultados porcat

o comooli sugirió, también puedes usar la agrupación de comandos:

$ { grep -vFf test2.csv test1.csv; grep -vFf test1.csv test2.csv; }
100,300,500,700
100,4,2,1,7
21,22,23,24,25
50,25,700,5

O simplemente ejecute uno tras otro, ya que ambos escriben en STDOUT y finalmente se agregarán:

$ grep -vFf test2.csv test1.csv; grep -vFf test1.csv test2.csv
100,300,500,700
100,4,2,1,7
21,22,23,24,25
50,25,700,5

Respuesta3

Si el orden de las filas no es relevante, utilice awko perl:

awk '{seen[$0]++} END {for (i in seen) {if (seen[i] == 1) {print i}}}' 1.csv 2.csv

Úselo greppara obtener las líneas comunes y filtrarlas:

grep -hxvFf <(grep -Fxf 1.csv 2.csv) 1.csv 2.csv

El grep interno obtiene las líneas comunes, luego el grep externo encuentra líneas que no coinciden con estas líneas comunes.

Respuesta4

Dado que no es necesario conservar el orden, simplemente:

sort test1.csv test2.csv | uniq -u
  • sort test1.csv test2.csv: fusiona y ordena test1.csvytest2.csv
  • uniq -u: imprime solo las líneas que no tienen duplicados

información relacionada