«Ungrep» - какие шаблоны не совпадают


13

Я ищу команду или скрипт, чтобы сделать следующее - учитывая:

file1.txt:

abcd
efgh 
ijkl
mnop

file2.txt:

123abcd123
123efgh123
123mnop123

Я хочу команду, которая делает что-то вроде этого:

ungrep file1.txt file2.txt

и возвращает следующее:

ijkl

Другими словами, он дает мне строки в file1.txt, которые не будут возвращать никаких результатов для файла file2.txt. Я знаю, что могу сделать это, перебирая file1.txt, подбирая 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
Вы можете достичь того же эффекта без хитрости grep:, sort file1.txt <(grep -of file1.txt file2.txt) | uniq -uно, как и ваше решение, это работает только тогда, когда файл шаблона на самом деле не содержит метасимволов регулярных выражений.
Ричи

@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, заключен в скобки. Оператор in , который проверяет существование определенного элемента массива, не должен заставлять этот элемент существовать. Любой другая ссылка на несуществующий элемент массива должна автоматически создать его. " Это можно найти, прокрутив параграф или два отсюда .
jw013

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