Se seu objetivo é encontrar linhas comuns ou incomuns, comm
seria meu comando aqui.
Ele compara dois arquivos e mostra - em três colunas - linhas exclusivas para o arquivo 1, linhas exclusivas para o arquivo 2 e linhas que aparecem nos dois arquivos, respectivamente. Você pode passar sinalizadores para suprimir qualquer uma dessas saídas também. Por exemplo comm -1 file1 file2
, suprimirá a primeira coluna, as coisas exclusivas do arquivo1. comm -12 file1 file2
mostraria apenas coisas nos dois arquivos.
Há uma grande ressalva: a entrada deve ser classificada. Nós podemos contornar isso.
Isso mostra tudo no abc que não está no mno:
comm -23 <(sort abc.txt) <(sort mno.txt)
E você pode canalizar isso wc -l
para obter uma contagem.
O motivo comm
é que, uma vez que os arquivos são classificados, a comparação lado a lado é computacionalmente muito simples. Se você está lidando com milhões deles, isso fará a diferença.
Isso pode ser demonstrado com alguns arquivos simulados. Eu tenho um computador bastante rápido, para mostrar a diferença entre abordagens, preciso de um conjunto de amostras gigantesco. Eu fui para 10 milhões de strings de 10 caracteres por arquivo.
$ cat /dev/urandom | tr -dc '0-9' | fold -w 10 | head -10000000 > abc.txt
$ cat /dev/urandom | tr -dc '0-9' | fold -w 10 | head -10000000 > mno.txt
$ time comm -23 <(sort abc.txt) <(sort mno.txt) | wc -l
... 0m10.653s
$ time grep -Fcxv -f abc.txt mno.txt
... 0m23.920s
$ time grep -Fcwv -f abc.txt mno.txt
... 0m40.313s
$ time awk 'NR==FNR{a[$0]++};NR!=FNR && a[$0]' abc.txt mno.txt | wc -l
... 0m12.161s
A classificação é o que leva a maior parte do tempo na minha. Se fingirmos que o abc.txt é estático, podemos pré-classificá-lo e isso torna as comparações futuras muito mais rápidas:
$ sort abc.txt abc-sorted.txt
$ time comm -23 abc-sorted.txt <(sort mno.txt) | wc -l
... 0m7.426s
Você pode olhar para eles e considerar alguns segundos irrelevantes, mas devo destacar que eles estão sendo executados em uma máquina de ponta. Se você quiser fazer isso em um (por exemplo) Raspberry Pi 3, verá mudanças muito mais lentas e a diferença aumentará a um ponto que realmente importa.
grep -cxvFf abc.txt mno.txt
?fgrep
,egrep
suplentes são supostamente obsoleta (em favor degrep -F
,grep -E
- embora eu não tenho certeza se alguém acredita que eles nunca vão embora-x
ao usar-F
?abcdef
, isso deve ser considerado como uma correspondência ou nãoabcd
?Poderíamos usar o awk para fazer o trabalho passando dois arquivos, primeiro o arquivo padrão, depois o arquivo que queremos verificar. Quando estamos lendo o primeiro arquivo, sabemos que
NR==FNR
e nesse momento podemos ler linhas na matriz. QuandoNR!=FNR
verificamos se o array para essa linha está definido.Por outro lado, podemos negar o padrão para imprimir as linhas que não estão em
abc.txt
E se quisermos imprimir a contagem daqueles que podemos empregar
sort
ewc
:fonte
abc.txt
-mno.txt
qual é{xyz, pqrs}
.Se uma das listas de palavras não estiver classificada, seria mais rápido usar uma estrutura de dados de conjunto eficiente para lembrar as palavras comuns.
Pitão
Uso:
Python (mais eficiente)
Se você deseja economizar um pouco de memória para armazenamento intermediário e tempo de execução, pode usar este programa um pouco mais difícil de entender:
atuação
Dado
abc.txt
emno.txt
com 1 milhão de linhas não ordenadas de 10 caracteres aleatórios de dígitos ASCII cada (consulte a resposta de Oli para a configuração):vs.
total: 23 segundos
fonte