Como comparar dois arquivos diferentes linha por linha no unix?

13

Arquivo1:

123
234
345
456

Arquivo2:

123
234
343
758

Saída esperada: Arquivo3:

TRUE
TRUE
FALSE
FALSE

portanto, o código deve comparar dois arquivos e imprimir 'TRUE' se corresponder, caso contrário, deve imprimir 'FALSE' no novo arquivo. Alguém poderia fornecer a solução para isso?

Velu
fonte
10
O que acontece se os dois arquivos tiverem tamanho desigual? Com que parte da solução desse problema você está tendo problemas?
Kusalananda
9
Você pode querer dar uma olhada diff.
Panki
2
Outro comando útil nessas situações é comm. Facilita a lista de linhas que ambos os arquivos têm em comum ou são exclusivos para um ou outro.
Giacomo Alzetta
1
@GiacomoAlzetta O problema commé que ele requer entrada classificada. Além do fato de que o exemplo na questão não tem entrada classificada, a questão nunca afirma que este é os dados reais que está sendo usado e nunca diz nada sobre a ordenação dos dados.
Kusalananda
2
O nltruque de αғsнιη é útil commpara impor classificação nos arquivos.
Glenn Jackman

Respostas:

56

Use o diffcomando a seguir, em bashou em qualquer outro shell que suporte <(...) substituições de processo ou você pode emular como mostrado aqui :

diff --new-line-format='FALSE'$'\n' \
     --old-line-format='' \
     --unchanged-line-format='TRUE'$'\n' \
<(nl file1) <(nl file2)

A saída seria:

TRUE
TRUE
FALSE
FALSE

--new-line-format='FALSE'$'\n, imprima FALSEse as linhas forem diferentes e, com a --old-line-format=''desativação da saída, se a linha for diferente para o arquivo1, que é conhecido como comando file to diff antigo (também podemos trocá-los, o que significa que um deles deve imprimir FALSEoutro deve ser desativado.)

--unchanged-line-format='TRUE'$'\n', imprima TRUEse as linhas forem iguais. a $'\n'sintaxe de escape estilo C é usada para imprimir uma nova linha após cada saída de linha.

αғsнιη
fonte
24

Supondo que os arquivos não contenham caracteres de tabulação:

$ paste file1 file2 | awk -F '\t' '{ print ($1 == $2 ? "TRUE" : "FALSE") }'
TRUE
TRUE
FALSE
FALSE

Isso é usado pastepara criar duas colunas delimitadas por tabulações, com o conteúdo dos dois arquivos em qualquer coluna. O awkcomando compara as duas colunas em cada linha e imprime TRUEse as colunas forem iguais e, caso contrário, será impresso FALSE.

Kusalananda
fonte
10

Supondo que os dois arquivos tenham o mesmo número de linhas:

awk '{getline f2 < "file2"; print f2 == $0 ? "TRUE" : "FALSE"}' file1

Isso está fazendo uma comparação numérica se as sequências a serem comparadas forem números e lexicais de outra forma. Por exemplo, 100e 1.0e2seria considerado idêntico. Mude para f2"" == $0para forçar uma comparação lexical em qualquer caso.

Dependendo da awkimplementação, a comparação lexical será feita como se estivesse usando memcmp()(comparação de bytes a bytes) ou como se estivesse usando strcoll()(se as duas cadeias são iguais na ordem de intercalação da localidade). Isso pode fazer a diferença em alguns locais onde a ordem não está definida corretamente para alguns caracteres, nem em todas as entradas de dígitos decimais, como na sua amostra.

Stéphane Chazelas
fonte
7

Python 3

with open('file1') as file1, open('file2') as file2:
    for line1, line2 in zip(file1, file2):
        print(line1 == line2)

Resultado:

True
True
False
False

Se você precisar TRUEe FALSEem maiúsculas, substitua a linha de impressão por uma destas:

print(str(line1 == line2).upper())
print('TRUE' if line1 == line2 else 'FALSE')
wjandrea
fonte
2
No Python 2, faça um import itertoolsprimeiro e, em seguida, use em itertools.izipvez de zip. Caso contrário, ele lerá os dois arquivos na memória, possivelmente usando muita memória.
pts
4

Em bash, lendo cada arquivo em um whileloop, comparando as linhas de leitura e imprimindo TRUEou FALSEapropriadamente:

while IFS= read -r -u3 line1; IFS= read -r -u4 line2; do
    [[ $line1 == $line2 ]] && echo TRUE || echo FALSE
done 3<file1 4<file2

As duas chamadas para readleituras do descritor de arquivo 3 e 4, respectivamente. Os arquivos são redirecionados para estes com dois redirecionamentos de entrada no loop.

Glenn Jackman
fonte
0
Tried with awk command and it worked fine


awk 'NR==FNR{a[$1];next}{if ($1 in a){print "TRUE"} else{print "False"}}' file1 file2

resultado

TRUE
TRUE
False
False
Praveen Kumar BS
fonte