Eu tenho "test1.csv" e contém
200,400,600,800
100,300,500,700
50,25,125,310
e test2.csv e contém
100,4,2,1,7
200,400,600,800
21,22,23,24,25
50,25,125,310
50,25,700,5
agora
diff test2.csv test1.csv > result.csv
é diferente de
diff test1.csv test2.csv > result.csv
Não sei qual é a ordem correta, mas quero outra coisa, ambos os comandos acima produzirão 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
Quero gerar apenas a diferença, portanto results.csv deve ficar assim
100,300,500,700
100,4,2,1,7
21,22,23,24,25
50,25,700,5
Eu tentei diff -q
e diff -s
mas eles não funcionaram. A ordem não importa, o que importa é que quero ver apenas a diferença, sem > nem < nem espaço em branco.
grep -FvF
funcionou em arquivos menores, não em arquivos grandes
o primeiro arquivo contém mais de 5 milhões de linhas, o segundo arquivo contém 1300.
então results.csv deve resultar em aproximadamente 4.998.700 linhas
Eu também tentei grep -F -x -v -f
o que não funcionou.
Responder1
Parece um trabalho 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
Conforme explicado em 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)
Isso -3
significa que apenas as linhas exclusivas de um dos arquivos serão impressas. No entanto, eles são recuados de acordo com o arquivo em que foram encontrados. Para remover a guia, use:
$ 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
Nesse caso, você nem precisa classificar os arquivos e pode simplificar o procedimento acima para:
comm -3 test1.csv test2.csv | tr -d '\t' > difference.csv
Responder2
Usando grep
com bash
substituição de processo:
$ 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 salvar a saída 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á as linhas exclusivas apenas paratest1.csv
grep -vFf test1.csv test2.csv
encontrará as linhas exclusivas apenas paratest2.csv
Finalmente estamos resumindo os resultados por
cat
Ou comoOli sugeriu, você também pode usar o agrupamento 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
Ou apenas execute um após o outro, pois ambos estão escrevendo para STDOUT e serão adicionados:
$ 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
Responder3
Se a ordem das linhas não for relevante, use awk
ou perl
:
awk '{seen[$0]++} END {for (i in seen) {if (seen[i] == 1) {print i}}}' 1.csv 2.csv
Use grep
para obter as linhas comuns e filtrá-las:
grep -hxvFf <(grep -Fxf 1.csv 2.csv) 1.csv 2.csv
O grep interno obtém as linhas comuns, então o grep externo encontra linhas que não correspondem a essas linhas comuns.
Responder4
Como o pedido não precisa ser preservado, basta:
sort test1.csv test2.csv | uniq -u
sort test1.csv test2.csv
: mescla e classificatest1.csv
etest2.csv
uniq -u
: imprime apenas as linhas que não possuem duplicatas