Come confrontare due diversi file riga per riga in unix?


13

file1:

123
234
345
456

file2:

123
234
343
758

Output previsto: File3:

TRUE
TRUE
FALSE
FALSE

quindi il codice dovrebbe confrontare due file e stampare "TRUE" se corrisponde altrimenti dovrebbe stampare "FALSE" nel nuovo file. Qualcuno potrebbe fornire la soluzione per questo?


10
Cosa succede se i due file hanno una lunghezza diversa? Con quale parte della soluzione di questo problema hai riscontrato problemi?
Kusalananda

9
Potresti dare un'occhiata diff.
Panki,

2
Altro comando utile in queste situazioni è comm. Consente di elencare facilmente le righe che entrambi i file hanno in comune o sono univoci per l'uno o l'altro.
Giacomo Alzetta,

1
@GiacomoAlzetta Il fatto commè che richiede un input ordinato. A parte il fatto che l'esempio in questione non hanno input ordinato, la questione non afferma che questo è i dati effettivi che viene utilizzato e non dice mai nulla l'ordinamento dei dati.
Kusalananda

2
Il nltrucco di αғsнιη è utile commper imporre l'ordinamento sui file.
Glenn Jackman,

Risposte:


56

Utilizzare il diffcomando come segue, in basho in qualsiasi altra shell che supporti le <(...) sostituzioni di processo oppure è possibile emularlo come mostrato qui :

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

L'output sarebbe:

TRUE
TRUE
FALSE
FALSE

--new-line-format='FALSE'$'\n, stampa FALSEse le linee erano diverse e con --old-line-format=''noi disabilitiamo l'output se la linea era diversa per file1, che è noto come comando da file vecchio a diff (potremmo scambiare anche questi, il che significa che uno di essi dovrebbe stampare FALSEun altro dovrebbe essere disabilitato).

--unchanged-line-format='TRUE'$'\n', stampa TRUEse le linee erano uguali. la $'\n'sintassi di escape in stile C viene utilizzata per stampare una nuova riga dopo ogni output di riga.


24

Supponendo che i file non contengano caratteri di tabulazione:

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

Questo utilizza pasteper creare due colonne delimitate da tabulazioni, con il contenuto dei due file in entrambe le colonne. Il awkcomando confronta le due colonne su ciascuna riga e stampa TRUEse le colonne sono uguali e altrimenti stampa FALSE.


10

Supponendo che entrambi i file abbiano lo stesso numero di righe:

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

Questo sta facendo un confronto numerico se le stringhe da confrontare sono numeri e lessicale altrimenti. Ad esempio, 100e 1.0e2sarebbe considerato identico. Passare a f2"" == $0per forzare un confronto lessicale in ogni caso.

A seconda awkdell'implementazione, il confronto lessicale verrà eseguito come se usando memcmp()(confronto byte-to-byte) o come usando strcoll()(se le due stringhe ordinano la stessa cosa nell'ordine di confronto della locale). Ciò può fare la differenza in alcune impostazioni locali in cui l'ordine non è definito correttamente per alcuni caratteri, non su tutte le cifre decimali come nell'esempio.


7

Python 3

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

Produzione:

True
True
False
False

Se necessario TRUEe FALSEin maiuscolo, sostituire la linea di stampa con una di queste:

print(str(line1 == line2).upper())
print('TRUE' if line1 == line2 else 'FALSE')

2
In Python 2, esegui una import itertoolsprima, quindi usa itertools.izipinvece di zip. Altrimenti leggerà entrambi i file in memoria, possibilmente usando troppa memoria.
Punti

4

In bash, leggendo da ciascun file in un whileciclo, confrontando le righe di lettura e stampando TRUEo FALSEopportunamente:

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

Le due chiamate readleggono rispettivamente dal descrittore di file 3 e 4. I file vengono reindirizzati a questi con due reindirizzamenti di input nel loop.


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

produzione

TRUE
TRUE
False
False
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.