В файле с двумя строками слов, grep только те строки, которые имеют оба слова из белого списка
У меня есть файл1:
green
yellow
apple
mango
и файл2:
red apple
blue banana
yellow mango
purple cabbage
Мне нужно найти элементы из file2, где оба слова принадлежат списку в file1. Итак, это должно показать:
желтое манго
Я старался:
awk < file2 '{if [grep -q $1 file1] && [grep -q $2 file1]; then print $0; fi}'
Я получаю синтаксическую ошибку.
3 ответа
Это сделает свое дело:
$ awk 'NR==FNR{a[$0];next}($1 in a)&&($2 in a)' file1 file2
yellow mango
Объяснение:
NR
это особый awk
переменная отслеживает текущую строку на входе и FNR
отслеживает текущую строку в каждом отдельном файле, поэтому условие NR==FNR
верно только когда мы в первом файле. a
является ассоциативным массивом, где ключи - каждая уникальная строка в первом файле. $0
значение текущей строки в awk
, next
оператор переходит на следующую строку в файле, чтобы следующая часть пропуска не выполнялась. Последняя часть прямолинейна, если первое поле $1
находится в массиве a
а во втором поле выведите текущую строку. Блок по умолчанию в awk
является {print $0}
так что это неявно.
Вы можете сделать это с помощью bash, sed и grep:
grep -f <(sed 's/^/^/' file1) file2 | grep -f <(sed 's/$/$/' file1)
это немного неясно, поэтому я разобью это:
grep -f <file>
читает последовательность шаблонов из файла и будет соответствовать любому из них.
<(...)
является bash
процесс подстановки и выполнит команду оболочки и создаст псевдофайл с выводом, который можно использовать вместо имени файла.
sed 's/^/^/' file1
вставляет ^
символ в начале каждой строки в файле1, превращая строки в шаблоны, которые будут соответствовать первому слову файла2.
sed 's/$/$/' file1
вставляет $
символ в конце, поэтому шаблоны будут соответствовать второму слову.
Редактировать: Использовать:
grep -f <(sed 's/^/^/;s/$/\b/' file1) file2 | grep -f <(sed 's/$/$/;s/^/\b/' file1)
чтобы обойти проблему, на которую указал Джонатан в своем комментарии.
Это очень хакерский подход, и, вероятно, его осуждают многие разработчики grep/sed. Кроме того, это, вероятно, зависит от терминала. Вы были предупреждены.
GNU grep в цветном режиме выделяет фрагменты входных данных, которые были сопоставлены с одним из шаблонов, что теоретически может использоваться в качестве теста для полного соответствия. Здесь это даже работает на практике, то есть с некоторой помощью GNU sed:
grep --color=always -f file1 file2 | sed -n '/^\x1b.*\x1b\[K *\x1b.*\x1b\[K$/ { s/\x1b\[K//g; s/\x1b[^m]*m//gp }'
Выход:
yellow mango
Обратите внимание, что шаблон sed предполагает использование столбцов, разделенных пробелами, в file2
,