Wyprowadzić wspólne linie (podobieństwa) dwóch plików tekstowych (przeciwieństwo diff)?


21

Różnicowanie to świetne narzędzie do wyświetlania zmian między dwoma plikami. Ale jak wyświetlić podobieństwa dwóch plików tekstowych (ignorując różnice)?

Tzn. Przykładowe dane wejściowe:

a:
Foo Bar
X
Hello
World
42

b:
Foo Baz
Hello
World
23

Pseudo wyjście (coś takiego):

@@ 2,3
=Hello World

Samo sortowanie obu plików i używanie komunikatora nie wystarczy, ponieważ w takim przypadku informacje o linii zostaną utracone.

Odpowiedzi:


24

Co powiesz na użycie diff, nawet jeśli nie chcesz diff? Spróbuj tego:

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

Oto, co otrzymuję z przykładowymi danymi:

$ 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
Możesz uniknąć osadzania dosłownego nowego wiersza w ten sposób:...%df'$'\n''%<'...
Wstrzymano do odwołania.

1
Możesz to również zrobić w następujący sposób: ... --unchanged-group-format="@@ %dn,%df%c'\012'%<" ...(Uwaga na podwójne cudzysłowy.)
Wstrzymano do odwołania.

Świetna sprawa! Nie znałem tych opcji, ponieważ właśnie spojrzałem na stronę man diff ...
maxschlepzig

Używam diff --version diff (GNU diffutils) 2.8.1 I pojawia się następujący błąd: diff: opcje stylu wyjścia sprzeczne diff: Wypróbuj `diff --help ', aby uzyskać więcej informacji.
Sujay,

Pojawił się komunikat „error: diff: sprzeczne opcje stylu wyjściowego diff”, ponieważ zdefiniowałem alias diff. Użyj, which diffaby sprawdzić, czy to twój problem.
justinjhendrick

14
grep -Fxf file1 file2

-Foznacza dopasowanie zwykłych ciągów (nie wyrażeń regularnych), -xoznacza tylko dopasowania całej linii, -foznacza pobranie „wzorców” (tj. linii) z pliku o nazwie jako argument


3
Nie są -fi -Fwymieniane ?. Tak przynajmniej jest w mojej grepwersji. Muszę podać file2dane wejściowe do -fargumentu, jak cat file1 | grep -Fxf file2, a następnie działa.
Birei

To nie zadziałało dla mnie.
Chaminda Bandara

7

commmoże być użyte. man commdla wszystkich opcji, ale będziesz chciał użyć, comm -12 ...aby wyświetlić tylko linie, które istnieją na obu wejściach.

Jak zauważyli ludzie, najpierw musisz przekazać swoje uwagi sort.


1
Hm, to działa tylko dla wspólnych linii, które mają ten sam numer linii w obu plikach.
maxschlepzig

2
comm wydaje się być tylko dla posortowanych plików i nie daje tego użytecznego wyjścia dla przypadku użycia OP. Jego przykład: $ comm -12 ab Hello World comm: plik 1 nie jest posortowany comm: plik 2 nie jest posortowany
Marcel Stimberg

@maxschlepzig: powinieneś posortować swoje pliki przed przekazaniem ich do komunikatora.
Hemant,

2
Jednak sortując pozbywasz się wszystkich informacji o położeniu wspólnych linii. Nie posortowałbyś plików przed porównaniem ich z diff.
Marcel Stimberg

7

Nie sądzę, aby istniało jedno polecenie, które robi to, co chcesz. Możesz jednak spróbować połączyć wyjście diffz grep. Jeśli pliki tekstowe zawierają żadnego z bohaterów |, <, >dodaje daje nieco przydatnych wyjście:

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

Spróbuj tego:diff --width=155 --left-column --side-by-side a b | grep -n -v '|' | sed 's/ *($//'
Wstrzymano do odwołania.

wygląda to lepiej - ale musisz wstawić <i> w grep, aby pozbyć się również dodanych linii w obu plikach.
Marcel Stimberg

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.