"Зняти" - які шаблони не збігаються


13

Я шукаю команду чи сценарій, щоб зробити наступне:

file1.txt:

abcd
efgh 
ijkl
mnop

file2.txt:

123abcd123
123efgh123
123mnop123

Я хочу команду, яка робить щось подібне:

ungrep file1.txt file2.txt

і повертає наступне:

ijkl

Іншими словами, він дає мені рядки у file1.txt, які не повернуть жодних результатів на грепі файлу2.txt. Я знаю, що я можу це зробити, повторивши файл file1.txt, grepping file2.txt для кожного рядка та зберігаючи результат, і вивести будь-які рядки, де результат порожній, але я сподівався на більш ефективний спосіб зробити це.

Відповіді:


18

З GNU grepслід працювати наступним чином. Використовуючи -fопцію, передайте file1.txtяк "файл шаблону", але також передайте його вдруге як файл даних. Використовуйте -oдля повідомлення лише про відповідні частини. Нарешті витягує ті слова, які відповідають лише один раз - вони відповідають рядкам, у file1.txtяких не знайдено відповідності file2.txt.

grep -h -o -f  file1.txt file2.txt file1.txt | sort | uniq -u
ijkl

Дуже хороший опис. Дякую та +1
unxnut

4
Ви можете домогтися такого ж ефекту без хитрості хитрості:, sort file1.txt <(grep -of file1.txt file2.txt) | uniq -uале, як і ваше рішення, це працює лише тоді, коли файл шаблону насправді не містить регекс-метахарактерів.
rici

@rici, це дуже хороший момент
iruvar

2
Поліпшення:grep -oFf file1.txt file2.txt | sort file1.txt - | uniq -u
Стефан Шазелас

10

Ви можете це зробити awkтак:

awk '
  NR == FNR {w[$0]; next}
  {for (i in w) if (index($0,i)) delete w[i]}
  END {for (i in w) print i}' file1.txt file2.txt

Використовуючи index, ми шукаємо підрядки, а не відповідність регулярним виразам.

Оскільки ми видаляємо слово з масиву, як тільки знайдемо відповідність, уникаємо зайвих пошуків.


1
Я би прийняв лише це. Він не викликає будь-якого сортування O (n log n) і не дивно виходить з ладу, коли шаблони містять регекс-метасимволи і можуть бути розширені для підтримки регулярних виразів.
Каз

Я не можу повірити, що просто оцінка w[$0]має побічний ефект від додавання ключа до масиву.
Каз

1
@Kaz, так, це може заплутати, і ви знайдете багато сценаріїв, які не свідомо виділяють елементи масиву ненавмисно, роблячи if (a[$1])замість цього, if ($1 in a)наприклад. Це справа кожного , awkвключаючи оригінал awkі nawk, але , дивлячись на стандартних вчора, я не міг знайти це зазначено.
Стефан Шазелас

1
@Kaz Ось цитата POSIX: "Додаток повинен гарантувати, що багатомірний індекс, що використовується разом із оператором в операторі, сковується в дужках. Оператор in , який тестує наявність певного елемента масиву, не повинен спричиняти існування цього елемента. Будь-який інша посилання на неіснуючий елемент масиву автоматично створює його. " Це можна знайти, прокручуючи абзац або два внизу .
jw013

1
Поки file1це не величезна (для деякої величини величезна), я вважаю за краще це рішення, оскільки воно не потребує сортування, file2і, як очікується, буде набагато ефективнішим.
jw013
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.