Grep поиск двух слов в строке

Я пытался найти способ отфильтровать строку, в которой есть слова "лимон" и "рис". Я знаю, как найти "лимон" или "рис", но не два из них. Они не обязательно должны быть рядом друг с другом, просто одна и та же строка текста.

"Оба в одной строке" означает ""рис", за которым следуют случайные символы, за которыми следует "лимон" или наоборот".

В регулярном выражении это rice.*lemon или lemon.*rice. Вы можете объединить это с помощью |:

grep -E 'rice.*lemon|lemon.*rice' some_file

Если вы хотите использовать обычные регулярные выражения вместо расширенных (-E) вам нужна обратная косая черта перед |:

grep 'rice.*lemon\|lemon.*rice' some_file

Для большего количества слов, которые быстро становятся немного длинноватыми, и обычно проще использовать несколько вызовов grep, например:

grep rice some_file | grep lemon | grep chicken

Вы можете передать выходные данные первой команды grep в другую команду grep, и это будет соответствовать обоим шаблонам. Итак, вы можете сделать что-то вроде:

grep <first_pattern> <file_name> | grep <second_pattern>

или,

cat <file_name> | grep <first_pattern> | grep <second_pattern>

Пример:

Давайте добавим некоторое содержимое в наш файл:

$ echo "This line contains lemon." > test_grep.txt$ echo "This line contains rice." >> test_grep.txt$ echo "This line contains both lemon and rice." >> test_grep.txt$ echo "This line doesn't contain any of them." >> test_grep.txt$ echo "This line also contains both rice and lemon." >> test_grep.txt

Что содержится в этом файле:

$ cat test_grep.txt This line contains lemon.This line contains rice.This line contains both lemon and rice.This line doesn't contain any of them.This line also contains both rice and lemon.

Теперь давайте определим, чего мы хотим:

$ grep rice test_grep.txt | grep lemonThis line contains both lemon and rice.This line also contains both rice and lemon.

Мы получаем только те линии, где совпадают оба шаблона. Вы можете расширить это и передать выходные данные в другую команду grep для дальнейших совпадений "И".

Хотя в вопросе задается "grep", я подумал, что было бы полезно опубликовать простое решение "awk":

awk '/lemon/ && /rice/'

Это может быть легко расширено с помощью большего количества слов или других логических выражений, кроме 'и'.

Еще одна идея поиска совпадений в любом порядке заключается в использовании:

grep с помощью -P (Совместимость с Perl) вариант и регулярное выражение с положительным обзором (?=(regex)):

grep -P '(?=.*?lemon)(?=.*?rice)' infile

или вы можете использовать ниже, вместо этого:

grep -P '(?=.*?rice)(?=.*?lemon)' infile
  • То .*? означает сопоставление любых символов . это происходит ноль или более раз * хотя они являются необязательными, за ними следует шаблон(rice или lemon). В ? делает все необязательным перед ним (означает ноль или один раз всего совпадающего .*)

(?=pattern): Позитивный взгляд: Конструкция позитивного взгляда представляет собой пару круглых скобок, за открывающей круглой скобкой следует знак вопроса и знак равенства.

Таким образом, это вернет все строки, содержащие оба lemon и rice в случайном порядке. Также это позволит избежать использования |s и удвоенный greps.


Внешние ссылки:
Расширенные темы Grep
Позитивный взгляд – GREP для дизайнеров

grep -e foo -e goo

Вернет совпадения либо для foo, либо для goo

Если мы признаем, что предоставление ответа, который не grep основанный является приемлемым, как и приведенный выше ответ, основанный на awk, я бы предложил простой perl линия, подобная:

$ perl -ne 'print if /lemon/ and /rice/' my_text_file

Поиск может быть выполнен с игнорированием случая с некоторыми / всеми словами, такими как /lemon/i and /rice/i. На большинстве машин Unix / Linux perl в любом случае установлен так же, как и awk.

Вот сценарий для автоматизации решения grep piping:

#!/bin/bash# Use filename if provided as environment variable, or "foo" as defaultfilename=${filename-foo}grepand () {# disable word splitting and globbingIFS=set -fif [[ -n $1 ]]thengrep -i "$1" ${filename} | filename="" grepand "${@:2}"else# If there are no arguments, assume last command in pipe and print everythingcatfi}grepand "$@"

Чтобы найти все строки внутри файла, вы можете запустить grep в цикле FOR: regular expression - How to run grep with multiple AND patterns? - Unix & Linux Stack Exchange