як показати спільні лінії (зворотний розл.)?


170

У мене є ряд текстових файлів, для яких я б хотів знати спільні рядки, а не ті, які між ними відрізняються. Командний рядок unix або windows добре.

foo:

linux-vdso.so.1 =>  (0x00007fffccffe000)
libvlc.so.2 => /usr/lib/libvlc.so.2 (0x00007f0dc4b0b000)
libvlccore.so.0 => /usr/lib/libvlccore.so.0 (0x00007f0dc483f000)
libc.so.6 => /lib/libc.so.6 (0x00007f0dc44cd000)

бар:

libkdeui.so.5 => /usr/lib/libkdeui.so.5 (0x00007f716ae22000)
libkio.so.5 => /usr/lib/libkio.so.5 (0x00007f716a96d000)
linux-vdso.so.1 =>  (0x00007fffccffe000)

Отже, з огляду на ці два файли над виходом потрібної утиліти було б схожим file1:line_number, file2:line_number == matching text (просто пропозиція, мені дійсно все одно, що таке синтаксис):

foo:1, bar:3 == linux-vdso.so.1 =>  (0x00007fffccffe000)

Дякую.


@ChristopherSchultz Моя помилка. 1-й рядок у 1-му прикладі повинен відповідати останньому рядку у 2-му прикладі. Дякуємо за те, що ви зрозуміли помилку; змінюючись.
matt wilkie

1
Ще одне подібне запитання з хорошими відповідями: unix.stackexchange.com/questions/1079/…
MortezaE

Відповіді:


210

На * nix, ви можете використовувати ком . Відповідь на питання:

comm -1 -2 file1.sorted file2.sorted 
# where file1 and file2 are sorted and piped into *.sorted

Ось повне використання comm:

comm [-1] [-2] [-3 ] file1 file2
-1 Suppress the output column of lines unique to file1.
-2 Suppress the output column of lines unique to file2.
-3 Suppress the output column of lines duplicated in file1 and file2. 

Також зауважте, що важливо сортувати файли перед тим, як використовувати кому, як зазначено на сторінках man.


3
comm [-1] [-2] [-3] файл1 файл2 -1 Придушіть вихідний стовпець рядків, унікальних для file1. -2 Придушити вихідний стовпець рядків, унікальних для file2. -3 Придушіть вихідний стовпчик рядків, дублюваних у file1 та file2.
ojblass

@ojblass: додав це до відповіді.
Метт Дж

6
Я виявив, що важливо, щоб файли були відсортовані перед використанням ком. Можливо, додайте це до відповіді.
matt wilkie

11
коротка відповідь на питання: comm -1 -2 file1 file2
greggles

6
Ви можете використовувати це, якщо ваші файли не відсортовані: comm -1 -2 <(сортування файлу1) <(сортування файлу2)
Кевін Вілер

56

Знайшов цю відповідь на запитання, вказане як дублікат . Я вважаю, що grep є більш зручним для адміністратора, ніж comm, тому якщо ви просто хочете, щоб набір відповідних ліній (корисний, наприклад, для порівняння CSV-файлів) просто використовуйте

grep -F -x -f file1 file2

або спрощена версія fgrep

fgrep -xf file1 file2

Крім того, ви можете використовувати file2*глобус і шукати спільні рядки з кількома файлами, а не лише з двома.

Деякі інші зручні варіанти включають

  • -n прапор, щоб показати номер рядка кожного зіставленого рядка
  • -c рахувати лише кількість рядків, які відповідають
  • -vвідображати лише рядки у file2, які відрізняються (або використовують diff).

Використання commшвидше, але ця швидкість виникає за рахунок того, що спочатку потрібно сортувати ваші файли. Це не дуже корисно як "зворотний розбіг".


спасибі Райдер, це може бути кориснішим, ніж кому для багатьох. Вам слід посилатись на відповідь на джерело (у Q в правій наві має понад півдесятка зв'язаних; у цьому потрібно трохи попрацювати). Було б також непогано знати, наскільки добре grep працює з не- або різним чином відсортованим входом, і може друкувати відповідні номери рядків збігів.
matt wilkie

1
@mattwilkie Я відчув необхідність повернутися та уточнити використання -vпрапора після того, як я сам його підсунув. Скажімо, у вас є два CSV-файли file1 та file2, і вони мають як рядки, що перекриваються, так і неперекриваються. Якщо ви хочете, щоб усі та лише рядки, що не перекривались, використовували fgrep -v file1 file2, повертають лише рядки, що не перекриваються у file2, і жоден із додаткових рядків, що не перекриваються у file1 . Для когось це може бути очевидно, але краще констатувати очевидне, ніж ризик неправильне тлумачення. У цьому конкретному випадку commнайкращим вибором є сортування файлів та їх використання .
Райдер

1
Дякую, що повернулися та роз’яснили Райдера. Додаткова увага відзначається і цінується (усе, коли легко, щоб старі речі не вислизали!). Я змінив прийняту відповідь, оскільки ком - це очевидно вибір громади, хоча особисто я все ще використовую це, коли сортування небажане накладні.
matt wilkie

2
Ще одне ускладнення при використанні grep: будь-який порожній рядок у першому файлі буде відповідати кожному рядку у другому файлі. Переконайтеся, що в file1ньому немає порожніх рядків, інакше файли будуть схожі
Крістофер Шульц

grep -Fxfце для мене
loxaxs

35

Тут задавались раніше: Команда Unix знаходити рядки, спільні у двох файлах

Ви також можете спробувати з perl (кредит тут )

perl -ne 'print if ($seen{$_} .= @ARGV) =~ /10$/'  file1 file2

1
Дякую. Я хотів би прийняти обидві відповіді, оскільки один вкладиш perl - це поперечна платформа. Comm отримує кивок, тому що це простіше.
matt wilkie

1
Ідеально. Використання cygwin-терміналу у Windows, і commвін не був доступний. Це була ідеальна альтернатива.
Qix - МОНІКА ПОМИЛИЛА

3
Це не стосується того, як упорядковані лінії. Це точніше, ніж ком.
enl8enmentnow


17

Щойно я дізнався команду comm з цієї нитки, але хотів додати щось додаткове: якщо файли не відсортовані, і ви не хочете торкатися оригінальних файлів, ви можете передавати вихідну команду сортування. Це залишає оригінальні файли недоторканими. Працює в баші, про інших снарядів сказати не можу.

comm -1 -2 <(sort file1) <(sort file2)

Це можна розширити для порівняння виводу команди, а не файлів:

comm -1 -2 <(ls /dir1 | sort) <(ls /dir2 | sort)

9

Найпростіший спосіб зробити це:

awk 'NR==FNR{a[$1]++;next} a[$1] ' file1 file2

Файли не потрібно сортувати.


1
Це на відміну від більшості відповідей тут, оскільки воно дозволяє реконструювати вихідні шаблони. У мене два файли, побудовані з однієї обгортки, з різним текстом, вставленим у декількох точках. Ця відповідь дозволила мені відновити обгортку.
Лукас Гонзе

1

Для інформації я зробив невеликий інструмент для Windows, що робить те саме, що і "grep -F -x -f file1 file2" (Як я не знайшов нічого еквівалентного цій команді в Windows)

Ось це: http://www.nerdzcore.com/?page=commonlines

Використання "CommonLines inputFile1 inputFile2 outputFile"

Вихідний код також доступний (GPL)


1

У Windows ви можете використовувати сценарій Powershell з CompareObject

compare-object -IncludeEqual -ExcludeDifferent -PassThru (get-content A.txt) (get-content B.txt)> MATCHING.txt | Out-Null #Find Matching Lines

ПорівнятиОб'єкт:

  • Включити рівний без -виключити різний: все
  • Виключити різного без -InclueEqual: нічого
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.