start cmd:> awk 'FNR == NR { oldfile[$0]=1; };
FNR != NR { if(oldfile[$0]==0) print; }' file1 file2
delta
omega
rho
phi
Eu preciso comparar dois arquivos txt. Cada linha dos dois arquivos txt contém entradas. Uma entrada por linha. O novo arquivo contém entradas que o antigo não possui. Eu tentei usar diff
e vimdiff
, mas isso não funciona porque as linhas podem estar em ordem diferente.
Por exemplo:
ANTIGO ARQUIVO
alpha
beta
gama
NOVO ARQUIVO
delta
omega
beta
alpha
gama
rho
phi
diff
e vimdiff
compara a linha 1 com a linha 1, a linha 2 com a linha 2, etc e, mesmo se eu classificar os dois arquivos, a comparação não terá êxito porque posso ter novos itens entre as versões classificadas, como "alfa , beta, rho "versus" alfa, beta, gama, rho ".
Como faço para obter uma lista de entradas que o novo arquivo tem que o antigo não possui?
Eu usaria grep
grep -Fxvf oldfile newfile
-F
: use o modo de string fixo (sem metacaracteres)
-x
: corresponde à linha inteira (não a uma substring)
-f oldfile
: leia as sequências a serem correspondidas a partir de oldfile
-v
: inverte a correspondência, ou seja, as sequências de impressão NÃO são encontradas em oldfile
Um comando awk
mais curto:
awk 'NR==FNR{a[$0];next}!($0 in a)' file1 file2
Se file1
puder estar vazio, substitua NR==FNR
por FILENAME==ARGV[1]
.
grep -Fxvf file2 file1
é lento para arquivos grandes:
$ jot -r 10000 1 100000 >file1;jot -r 10000 1 100000 >file2
$ time awk 'NR==FNR{a[$0];next}!($0 in a)' file1 file2 >/dev/null
0.015
$ time grep -Fxvf file2 file1 >/dev/null
36.758
$ time comm -13 <(sort file1) <(sort file2)>/dev/null
0.173
Se você precisar remover linhas repetidas, use
awk 'NR==FNR{a[$0];next}!b[$0]++&&!($0 in a)' file1 file2
ou
comm -13 <(sort file1) <(sort -u file2)
Se você não se importar com a ordem das entradas, classifique os dois arquivos e depois use comm
.
comm -13 <(sort old.txt) <(sort new.txt)
Ou se o seu shell não tiver substituição de processo:
sort old.txt >sorted.old.txt
sort new.txt >sorted.new.txt
comm -13 sorted.old.txt sorted.new.txt
Se a ordem das inscrições for importante, você pode usar grep
com as opções certas : -Fx
para corresponder exatamente a linhas completas, -v
para excluir linhas correspondentes e -f
para ler um arquivo contendo os padrões a serem excluídos.
grep -Fxv -f old.txt new.txt
No caso, se você precisar da maneira python
de fazê-lo.
#!/usr/bin/env python3.4
oldfp = open('/tmp/tmp.Q3JiYGY6fs/oldfile')
newfp = open('/tmp/tmp.Q3JiYGY6fs/newfile')
old = set([ x.strip() for x in oldfp.readlines() ])
new = set([ x.strip() for x in newfp.readlines() ])
print('Lines that are present only in newfile are \n{}\n\n{} '.format(42*'-', '\n'.join(list(new - old))))
E a saída será
Lines that are present only in newfile are
------------------------------------------
phi
rho
omega
delta
Tags files file-comparison