Eu tenho um arquivo grande A (composto por emails), uma linha para cada email. Eu também tenho outro arquivo B que contém outro conjunto de mensagens.
Qual comando eu usaria para remover todos os endereços que aparecem no arquivo B do arquivo A.
Portanto, se o arquivo A contiver:
A
B
C
e o arquivo B continha:
B
D
E
Em seguida, o arquivo A deve ser deixado com:
A
C
Agora sei que essa é uma pergunta que pode ter sido feita com mais frequência, mas só encontrei um comando online que me deu um erro com um delimitador ruim.
Qualquer ajuda seria muito apreciada! Alguém certamente apresentará uma frase inteligente, mas eu não sou o especialista em shell.
Respostas:
Se os arquivos estiverem classificados (eles estão no seu exemplo):
-23
suprime as linhas que estão nos dois arquivos ou apenas no arquivo 2. Se os arquivos não forem classificados, passe-ossort
primeiro ...Veja a página de manual aqui
fonte
comm -23 file1 file2 > file3
produzirá o conteúdo no arquivo1 e não no arquivo2, para o arquivo3. E,mv file3 file1
finalmente, limparia o conteúdo redundante no arquivo1.comm -23 file1 file2 | sponge file1
. Nenhuma limpeza necessária.grep -Fvxf <lines-to-remove> <all-lines>
Exemplo:
Resultado:
Explicação:
-F
: use cadeias literais em vez do BRE padrão-x
: considere apenas correspondências que correspondem à linha inteira-v
: imprimir sem correspondência-f file
: pegue padrões do arquivo fornecidoEsse método é mais lento em arquivos pré-classificados que outros métodos, pois é mais geral. Se a velocidade também for importante, consulte: Maneira rápida de encontrar linhas em um arquivo que não está em outro?
Aqui está uma automação rápida do bash para operação em linha:
GitHub upstream .
uso:
Consulte também: /unix/28158/is-there-a-tool-to-get-the-lines-in-one-file-that-are-not-in-another
fonte
awk para o resgate!
Esta solução não requer entradas classificadas. Você precisa fornecer o arquivo B primeiro.
retorna
Como funciona?
Observe que agora isso pode ser usado para remover palavras da lista negra.
com uma pequena alteração, ele pode limpar várias listas e criar versões limpas.
fonte
A\nC
, a escrita para um arquivo temporário primeiro e substituir o arquivo original... > tmp && mv tmp fileA
fileB
se não está vazio (0 bytes de comprimento), pois, se estiver, você obterá um resultado vazio em vez do conteúdo esperado defileA
. (Causa:FNR==NR
será aplicada afileA
então.)Outra maneira de fazer a mesma coisa (também requer entrada classificada):
No Bash, se os arquivos não forem pré-classificados:
fonte
Você pode fazer isso, a menos que seus arquivos sejam classificados
--new-line-format
é para linhas que estão no arquivo b, mas não em a,--old-..
é para linhas que estão no arquivo a, mas não em b,--unchanged-..
é para linhas que estão em ambos.%L
faz com que a linha seja impressa exatamente.para mais detalhes
fonte
comm
comando.comm
requer que os arquivos sejam classificados, portanto, se eles forem classificados, você poderá usar essa solução também. Você pode usar esta solução, independentemente do arquivo é ordenado ou não emboraEsse refinamento da boa resposta do @ karakfa pode ser notavelmente mais rápido para arquivos muito grandes. Como com essa resposta, nenhum dos arquivos precisa ser classificado, mas a velocidade é garantida em virtude das matrizes associativas do awk. Somente o arquivo de pesquisa é mantido na memória.
Essa formulação também permite a possibilidade de que apenas um campo específico ($ N) no arquivo de entrada seja usado na comparação.
(Outra vantagem dessa abordagem é que é fácil modificar o critério de comparação, por exemplo, para aparar os espaços em branco à esquerda e à direita.)
fonte
Você pode usar o Python:
fonte
Você pode usar -
diff fileA fileB | grep "^>" | cut -c3- > fileA
Isso funcionará para arquivos que não são classificados também.
fonte
Para remover linhas comuns entre dois arquivos, você pode usar o comando grep, comm ou join.
Isso exibe linhas do arquivo1 que não correspondem a nenhuma linha do arquivo2.
Isso exibe linhas do arquivo1 que não correspondem a nenhuma linha do arquivo2.
fonte