Quero comparar o arquivo1 com o arquivo2 e gerar um arquivo3 que contém as linhas do arquivo1 que não estão presentes no arquivo2.
Quero comparar o arquivo1 com o arquivo2 e gerar um arquivo3 que contém as linhas do arquivo1 que não estão presentes no arquivo2.
Respostas:
diff (1) não é a resposta, mas comm (1) é.
NAME
comm - compare two sorted files line by line
SYNOPSIS
comm [OPTION]... FILE1 FILE2
...
-1 suppress lines unique to FILE1
-2 suppress lines unique to FILE2
-3 suppress lines that appear in both files
assim
comm -2 -3 file1 file2 > file3
Os arquivos de entrada devem ser classificados. Se não forem, classifique-os primeiro. Isso pode ser feito com um arquivo temporário ou ...
comm -2 -3 <(sort file1) <(sort file2) > file3
desde que seu shell suporte substituição de processo (bash faz).
comm -23
O utilitário Unix diff
é feito exatamente para esse propósito.
$ diff -u file1 file2 > file3
Consulte o manual e a Internet para opções, diferentes formatos de saída, etc.
Considere o seguinte:
arquivo a.txt:
abcd
efgh
arquivo b.txt:
abcd
Você pode encontrar a diferença com:
diff -a --suppress-common-lines -y a.txt b.txt
O resultado será:
efgh
Você pode redirecionar a saída em um arquivo de saída (c.txt) usando:
diff -a --suppress-common-lines -y a.txt b.txt > c.txt
Isso vai responder à sua pergunta:
"... que contém as linhas no arquivo1 que não estão presentes no arquivo2."
-d
, o que fará diff
o possível para encontrar a menor diferença possível. -i
, -E
, -w
, -B
E --suppress-blank-empty
pode também ser útil, ocasionalmente, embora não sempre. Se você não sabe o que se encaixa no seu caso de uso, tente diff --help
primeiro (o que geralmente é uma boa ideia quando você não sabe o que um comando pode fazer).
Às vezes diff
é o utilitário de que você precisa, mas às vezes join
é mais apropriado. Os arquivos precisam ser pré-classificados ou, se você estiver usando um shell que suporte a substituição de processos, como bash, ksh ou zsh, você pode fazer a classificação em tempo real.
join -v 1 <(sort file1) <(sort file2)
Experimentar
sdiff file1 file2
Normalmente funciona muito melhor na maioria dos casos para mim. Você pode querer classificar os arquivos antes, se a ordem das linhas não for importante (por exemplo, alguns arquivos de configuração de texto).
Por exemplo,
sdiff -w 185 file1.cfg file2.cfg
sdiff <(sort file1) <(sort file2)
)
Se você precisa resolver isso com coreutils, a resposta aceita é boa:
comm -23 <(sort file1) <(sort file2) > file3
Você também pode usar sd (stream diff), que não requer classificação nem substituição de processo e suporta fluxos infinitos, assim:
cat file1 | sd 'cat file2' > file3
Provavelmente não é um grande benefício neste exemplo, mas ainda considere isso; em alguns casos você não poderá usar comm
nem grep -F
nem diff
.
Aqui está uma postagem de blog que escrevi sobre diffing streams no terminal, que apresenta o sd.
Muitas respostas já, mas nenhuma delas IMHO perfeito. A resposta de Thanatos deixa alguns caracteres extras por linha e a resposta de Sorpigal exige que os arquivos sejam classificados ou pré-classificados, o que pode não ser adequado em todas as circunstâncias.
Acho que a melhor maneira de obter as linhas que são diferentes e nada mais (não caracteres extras, sem re-ordenação) é uma combinação de diff
, grep
eawk
(ou similar).
Se as linhas não contêm nenhum "<", uma linha curta pode ser:
diff urls.txt* | grep "<" | sed 's/< //g'
mas isso removerá todas as instâncias de "<" (menos que, espaço) das linhas, o que nem sempre está OK (por exemplo, código-fonte). A opção mais segura é usar o awk:
diff urls.txt* | grep "<" | awk '{for (i=2; i<NF; i++) printf $i " "; print $NF}'
Este one-liner diffs ambos os arquivos, então filtra a saída do estilo ed do diff, então remove o "<" que o diff adiciona. Isso funciona mesmo se as linhas contiverem alguns "<".
diff a1.txt a2.txt | grep '> ' | sed 's/> //' > a3.txt
Tentei quase todas as respostas neste tópico, mas nenhuma foi completa. Depois de algumas trilhas acima, uma funcionou para mim. diff lhe dará diferença, mas com alguns charas especiais indesejados. onde suas linhas de diferença reais começam com '>'. então o próximo passo é fazer o grep das linhas começar com '>' e, em seguida, remover as mesmas com sed .
<
. Você verá isso se trocar a ordem dos arquivos de entrada. Mesmo se você fizesse isso, você iria querer omitir grep
usando mais sed: `diff a1 a2 | sed '/> / s ///' `Isso ainda pode quebrar linhas contendo >
ou <
na situação certa e ainda deixa linhas extras descrevendo os números das linhas. Se você queria experimentar esta abordagem uma maneira melhor seria: diff -C0 a1 a2 | sed -ne '/^[+-] /s/^..//p'
.
Você pode usar diff
com a seguinte formatação de saída:
diff --old-line-format='' --unchanged-line-format='' file1 file2
--old-line-format=''
, desabilite a saída para arquivo1 se a linha for diferente compare em arquivo2.
--unchanged-line-format=''
, desative a saída se as linhas forem iguais.