Output le linee comuni (somiglianze) di due file di testo (l'opposto di diff)?


21

Diff è un ottimo strumento per visualizzare le modifiche tra due file. Ma come visualizzare le somiglianze di due file di testo (ignorando le differenze)?

Cioè input di esempio:

a:
Foo Bar
X
Hello
World
42

b:
Foo Baz
Hello
World
23

Pseudo output (qualcosa del genere):

@@ 2,3
=Hello World

Ordinare entrambi i file e usare comm non è sufficiente, perché in tal caso le informazioni sulla linea vanno perse.

Risposte:


24

Che ne dici di usare diff, anche se non vuoi un diff? Prova questo:

diff --unchanged-group-format='@@ %dn,%df 
  %<' --old-group-format='' --new-group-format='' \
  --changed-group-format='' a.txt b.txt

Ecco cosa ottengo con i tuoi dati di esempio:

$ cat a.txt 
Foo Bar
X
Hello
World
42
$ cat b.txt 
Foo Baz
Hello
World
23
$ diff --unchanged-group-format='@@ %dn,%df
%<' --old-group-format='' --new-group-format='' \
  --changed-group-format='' a.txt b.txt
@@ 2,3
Hello
World

2
Puoi evitare di incorporare una nuova riga letterale come questa:...%df'$'\n''%<'...
Pausa fino a ulteriore avviso.

1
Puoi anche farlo in questo modo: ... --unchanged-group-format="@@ %dn,%df%c'\012'%<" ...(Nota le doppie virgolette.)
In pausa fino a nuovo avviso.

Roba fantastica! Non conoscevo queste opzioni, perché ho appena guardato la pagina man diff ...
maxschlepzig

Sto usando diff --version diff (GNU diffutils) 2.8.1 E ottengo il seguente errore: diff: opzioni di stile di output in conflitto diff: Prova `diff --help 'per maggiori informazioni.
Sujay,

Stavo ottenendo "errore: diff: opzioni di stile di output in conflitto diff" perché avevo un alias diff definito. Usa which diffper vedere se questo è il tuo problema.
justinjhendrick,

14
grep -Fxf file1 file2

-Fsignifica corrispondere stringhe semplici (non regexps), -xsignifica solo corrispondenze a linea intera, -fsignifica prendere 'modelli' (cioè linee) dal file chiamato come argomento


3
Non sono -fe -Fscambiato ?. Almeno nella mia grepversione è così. Ho bisogno di fornire un file2contributo -fall'argomento, come cat file1 | grep -Fxf file2, e quindi funziona.
Birei,

Questo non ha funzionato per me.
Chaminda Bandara,

7

commpuò essere utilizzato. man commper tutte le opzioni, ma ti consigliamo comm -12 ...di mostrare solo le linee esistenti in entrambi gli input.

Come le persone hanno sottolineato, è necessario prima passare l'input sort.


1
Hm, che funziona solo per le linee comuni che hanno lo stesso numero di riga in entrambi i file.
maxschlepzig,

2
comm sembra essere solo per file ordinati e non dare quell'utile output per il caso d'uso dell'OP. Il suo esempio: $ comm -12 ab Hello World comm: il file 1 non è nell'ordine ordinato comm: il file 2 non è nell'ordine ordinato
Marcel Stimberg

@maxschlepzig: dovresti ordinare i tuoi file prima di passarli alla comunicazione.
Hemant,

2
Ordinando, però, ti sbarazzi di tutte le informazioni sulla posizione delle linee comuni. Non dovrai nemmeno ordinare i file prima di confrontarli con diff.
Marcel Stimberg,

7

Non penso che ci sia un singolo comando che fa quello che vuoi che faccia. Puoi provare a combinare l'output di diffcon grep, però. Se i file di testo contengono nessuno dei personaggi |, <, >, il seguente fornisce in uscita un po 'utile:

$ diff --side-by-side a b | grep -n -v "[|<>]"
3:Hello                             Hello
4:World                             World

Prova questo:diff --width=155 --left-column --side-by-side a b | grep -n -v '|' | sed 's/ *($//'
In pausa fino a nuovo avviso.

sembra migliore, ma devi includere <e> nel grep per eliminare anche le righe aggiunte in entrambi i file.
Marcel Stimberg,

2

Dick Grune ha scritto una famiglia di strumenti per questo tipo di cose:

http://dickgrune.com/Programs/similarity_tester/

Esistono versioni che analizzano la sintassi di vari linguaggi, in modo che cose come le variabili rinominate possano essere viste invariate.

È confezionato come similarity-testerin Debian e Ubuntu.

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.