Existem dois arquivos chamados "a.txt" e "b.txt", ambos possuem uma lista de palavras. Agora, quero verificar quais palavras são extras em "a.txt" e não em "b.txt" .
Eu preciso de um algoritmo eficiente, pois preciso comparar dois dicionários.
Existem dois arquivos chamados "a.txt" e "b.txt", ambos possuem uma lista de palavras. Agora, quero verificar quais palavras são extras em "a.txt" e não em "b.txt" .
Eu preciso de um algoritmo eficiente, pois preciso comparar dois dicionários.
Respostas:
Se você possui o vim instalado, tente o seguinte:
vimdiff file1 file2
ou
vim -d file1 file2
você achará fantástico.
Classifique-os e use comm
:
comm -23 <(sort a.txt) <(sort b.txt)
comm
compara os arquivos de entrada (classificados) e, por padrão, gera três colunas: linhas exclusivas de a, linhas exclusivas de be linhas presentes em ambas. Especificando -1
, -2
e / ou -3
você pode suprimir a saída correspondente. Portanto, comm -23 a b
lista apenas as entradas exclusivas de a. Eu uso a <(...)
sintaxe para classificar os arquivos em tempo real, se eles já estiverem classificados, você não precisa disso.
comm
é mais eficiente porque faz o trabalho em uma única execução, sem armazenar o arquivo inteiro na memória. Como você está usando dicionários que provavelmente já estão classificados, você nem precisa sort
deles. O uso, grep -f file1 file2
por outro lado, carregará o todo file1
na memória e comparará cada linha file2
com todas essas entradas, o que é muito menos eficiente. É principalmente útil para pequenas, sem classificação -f file1
.
\n
também será incluído para fazer comparações.
Você pode usar a diff
ferramenta no linux para comparar dois arquivos. Você pode usar as opções - formato de grupo alterado e - formato de grupo alterado - para filtrar os dados necessários.
As três opções a seguir podem ser usadas para selecionar o grupo relevante para cada opção:
'% <' obtém linhas de FILE1
'%>' obtém linhas de FILE2
'' (string vazia) para remover linhas de ambos os arquivos.
Por exemplo: diff --changed-group-format = "% <" --unchanged-group-format = "" file1.txt file2.txt
[root@vmoracle11 tmp]# cat file1.txt
test one
test two
test three
test four
test eight
[root@vmoracle11 tmp]# cat file2.txt
test one
test three
test nine
[root@vmoracle11 tmp]# diff --changed-group-format='%<' --unchanged-group-format='' file1.txt file2.txt
test two
test four
test eight
Se você preferir o estilo de saída diff git diff
, poderá usá-lo com o --no-index
sinalizador para comparar arquivos que não estão em um repositório git:
git diff --no-index a.txt b.txt
Usando um par de arquivos com cerca de 200k seqüências de nomes de arquivos em cada um deles, eu comparei (com o time
comando interno) essa abordagem contra algumas das outras respostas aqui:
git diff --no-index a.txt b.txt
# ~1.2s
comm -23 <(sort a.txt) <(sort b.txt)
# ~0.2s
diff a.txt b.txt
# ~2.6s
sdiff a.txt b.txt
# ~2.7s
vimdiff a.txt b.txt
# ~3.2s
comm
parece ser o mais rápido de longe, enquanto git diff --no-index
parece ser a abordagem mais rápida para saída no estilo diff.
Atualização 2018-03-25 Na verdade, você pode omitir o --no-index
sinalizador, a menos que esteja dentro de um repositório git e queira comparar arquivos não rastreados dentro desse repositório. Nas páginas do manual :
Este formulário é para comparar os dois caminhos fornecidos no sistema de arquivos. Você pode omitir a opção --no-index ao executar o comando em uma árvore de trabalho controlada pelo Git e pelo menos um dos pontos de caminhos fora da árvore de trabalho ou ao executar o comando fora de uma árvore de trabalho controlada pelo Git.
Você também pode usar: colordiff : Exibe a saída do diff com cores.
Sobre o vimdiff : permite comparar arquivos via SSH, por exemplo:
vimdiff /var/log/secure scp://192.168.1.25/var/log/secure
Extraído de: http://www.sysadmit.com/2016/05/linux-diferencias-entre-dos-archivos.html
Além disso, não se esqueça do mcdiff - Visualizador de diferenças internas do GNU Midnight Commander .
Por exemplo:
mcdiff file1 file2
Aproveitar!
Use comm -13
(requer arquivos classificados) :
$ cat file1
one
two
three
$ cat file2
one
two
three
four
$ comm -13 <(sort file1) <(sort file2)
four
Aqui está a minha solução para isso:
mkdir temp
mkdir results
cp /usr/share/dict/american-english ~/temp/american-english-dictionary
cp /usr/share/dict/british-english ~/temp/british-english-dictionary
cat ~/temp/american-english-dictionary | wc -l > ~/results/count-american-english-dictionary
cat ~/temp/british-english-dictionary | wc -l > ~/results/count-british-english-dictionary
grep -Fxf ~/temp/american-english-dictionary ~/temp/british-english-dictionary > ~/results/common-english
grep -Fxvf ~/results/common-english ~/temp/american-english-dictionary > ~/results/unique-american-english
grep -Fxvf ~/results/common-english ~/temp/british-english-dictionary > ~/results/unique-british-english
sdiff -s file1 file2
foi útil.
Usando awk para isso. Arquivos de teste:
$ cat a.txt
one
two
three
four
four
$ cat b.txt
three
two
one
O awk:
$ awk '
NR==FNR { # process b.txt or the first file
seen[$0] # hash words to hash seen
next # next word in b.txt
} # process a.txt or all files after the first
!($0 in seen)' b.txt a.txt # if word is not hashed to seen, output it
Duplicatas são produzidas:
four
four
Para evitar duplicatas, adicione cada palavra recém-encontrada em a.txt ao seen
hash:
$ awk '
NR==FNR {
seen[$0]
next
}
!($0 in seen) { # if word is not hashed to seen
seen[$0] # hash unseen a.txt words to seen to avoid duplicates
print # and output it
}' b.txt a.txt
Resultado:
four
Se as listas de palavras forem separadas por vírgula, como:
$ cat a.txt
four,four,three,three,two,one
five,six
$ cat b.txt
one,two,three
você tem que fazer algumas voltas extras ( for
loops):
awk -F, ' # comma-separated input
NR==FNR {
for(i=1;i<=NF;i++) # loop all comma-separated fields
seen[$i]
next
}
{
for(i=1;i<=NF;i++)
if(!($i in seen)) {
seen[$i] # this time we buffer output (below):
buffer=buffer (buffer==""?"":",") $i
}
if(buffer!="") { # output unempty buffers after each record in a.txt
print buffer
buffer=""
}
}' b.txt a.txt
Saída desta vez:
four
five,six
diff a.txt b.txt
não é o suficiente?