Voglio confrontare file1 con file2 e generare un file3 che contiene le righe in file1 che non sono presenti in file2.
Voglio confrontare file1 con file2 e generare un file3 che contiene le righe in file1 che non sono presenti in file2.
Risposte:
diff (1) non è la risposta, ma comm (1) sì.
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
Così
comm -2 -3 file1 file2 > file3
I file di input devono essere ordinati. Se non lo sono, ordinali prima. Questo può essere fatto con un file temporaneo o ...
comm -2 -3 <(sort file1) <(sort file2) > file3
a condizione che la tua shell supporti la sostituzione del processo (bash lo fa).
comm -23
L'utilità Unix diff
è pensata esattamente per questo scopo.
$ diff -u file1 file2 > file3
Vedere il manuale e Internet per opzioni, diversi formati di output, ecc.
Considera questo:
file a.txt:
abcd
efgh
file b.txt:
abcd
Puoi trovare la differenza con:
diff -a --suppress-common-lines -y a.txt b.txt
L'output sarà:
efgh
Puoi reindirizzare l'output in un file di output (c.txt) utilizzando:
diff -a --suppress-common-lines -y a.txt b.txt > c.txt
Questo risponderà alla tua domanda:
"... che contiene le righe in file1 che non sono presenti in file2."
-d
, che farà del diff
suo meglio per trovare il più piccolo diff. -i
, -E
, -w
, -B
E --suppress-blank-empty
può anche essere utile a volte, anche se non sempre. Se non sai cosa si adatta al tuo caso d'uso, prova diff --help
prima (che è generalmente una buona idea quando non sai cosa può fare un comando).
A volte diff
è l'utilità di cui hai bisogno, ma a volte join
è più appropriata. I file devono essere preordinati o, se si utilizza una shell che supporta la sostituzione del processo come bash, ksh o zsh, è possibile eseguire l'ordinamento al volo.
join -v 1 <(sort file1) <(sort file2)
Provare
sdiff file1 file2
Di solito funziona molto meglio nella maggior parte dei casi per me. Potresti voler ordinare i file prima, se l'ordine delle righe non è importante (ad esempio alcuni file di configurazione del testo).
Per esempio,
sdiff -w 185 file1.cfg file2.cfg
sdiff <(sort file1) <(sort file2)
)
Se devi risolvere questo problema con coreutils, la risposta accettata è buona:
comm -23 <(sort file1) <(sort file2) > file3
Puoi anche usare sd (stream diff), che non richiede l'ordinamento né la sostituzione del processo e supporta flussi infiniti, in questo modo:
cat file1 | sd 'cat file2' > file3
Probabilmente non è un gran vantaggio in questo esempio, ma consideralo comunque; in alcuni casi non potrai usare comm
né grep -F
nédiff
.
Ecco un post sul blog che ho scritto sui diversi flussi sul terminale, che introduce sd.
Molte risposte già, ma nessuna di loro perfetta IMHO. La risposta di Thanatos lascia alcuni caratteri in più per riga e la risposta di Sorpigal richiede che i file siano ordinati o preordinati, il che potrebbe non essere adeguato in tutte le circostanze.
Penso che il modo migliore di ottenere le linee che sono differenti e nient'altro (niente caratteri aggiuntivi, non ri-ordinazione) è una combinazione di diff
, grep
e awk
(o simili).
Se le righe non contengono "<", una breve riga può essere:
diff urls.txt* | grep "<" | sed 's/< //g'
ma questo rimuoverà ogni istanza di "<" (minore di, spazio) dalle righe, il che non è sempre corretto (ad esempio il codice sorgente). L'opzione più sicura è usare awk:
diff urls.txt* | grep "<" | awk '{for (i=2; i<NF; i++) printf $i " "; print $NF}'
Questa riga di una riga differisce entrambi i file, quindi filtra l'output in stile ed di diff, quindi rimuove il "<" finale aggiunto da diff. Funziona anche se le righe contengono alcuni "<".
diff a1.txt a2.txt | grep '> ' | sed 's/> //' > a3.txt
Ho provato quasi tutte le risposte in questo thread, ma nessuna era completa. Dopo pochi sentieri sopra uno ha funzionato per me. diff ti darà la differenza ma con alcuni charas speciali indesiderati. dove le linee di differenza effettive iniziano con ">". quindi il passo successivo è quello di grep che le linee iniziano con '>' e seguite rimuovendo lo stesso con sed .
<
. Lo vedrai se cambi l'ordine dei file di input. Anche se lo facessi, dovresti omettere grep
usando più sed: `diff a1 a2 | sed '/> / s ///' `Questo può ancora interrompere le righe che contengono >
o <
nella giusta situazione e lascia ancora righe extra che descrivono i numeri di riga. Se si voleva provare questo approccio un modo migliore sarebbe: diff -C0 a1 a2 | sed -ne '/^[+-] /s/^..//p'
.
È possibile utilizzare diff
con la seguente formattazione di output:
diff --old-line-format='' --unchanged-line-format='' file1 file2
--old-line-format=''
, disabilita l'output per file1 se la riga era diversa confronta in file2.
--unchanged-line-format=''
, disabilita l'output se le righe fossero le stesse.