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 -q
y diff -s
no funcionaron. No importa el orden, lo que importa es que quiero ver solo la diferencia, ni > ni < ni espacios en blanco.
grep -FvF
funcionó 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 -3
significa 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 grep
con bash
sustitució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
grep -vFf test2.csv test1.csv
encontrará las líneas únicas para solotest1.csv
grep -vFf test1.csv test2.csv
encontrará las líneas únicas para solotest2.csv
Finalmente estamos resumiendo los resultados por
cat
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 awk
o perl
:
awk '{seen[$0]++} END {for (i in seen) {if (seen[i] == 1) {print i}}}' 1.csv 2.csv
Úselo grep
para 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 ordenatest1.csv
ytest2.csv
uniq -u
: imprime solo las líneas que no tienen duplicados