Grep, ищущий два слова в строке

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

46
задан 8 January 2018 в 07:11

7 ответов

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

В regex, который является rice.*lemon или lemon.*rice. Можно объединить то использование |:

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

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

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

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

grep rice some_file | grep lemon | grep chicken
62
ответ дан 22 November 2019 в 23:56

Можно передать вывод по каналу первой команды 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, что мы хотим:

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

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

26
ответ дан 22 November 2019 в 23:56

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

awk '/lemon/ && /rice/'

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

21
ответ дан 22 November 2019 в 23:56

Другая идея найти соответствия в любом порядке использует:

grep с -P (Совместимость Perl) опция и положительный предварительный regex (?=(regex)):

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

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

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

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

, Таким образом, это возвратится, все строки с содержит и lemon и rice в произвольном порядке. Также это избежит использования | с и удвоилось grep с.

<час>

Внешние ссылки:
Усовершенствованные Темы Grep
Положительное Предвидение †“GREP для Разработчиков

11
ответ дан 22 November 2019 в 23:56
grep -e foo -e goo

возвратит соответствия или для нечто или для липкой вещи

5
ответ дан 22 November 2019 в 23:56

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

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

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

1
ответ дан 22 November 2019 в 23:56

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

#!/bin/bash

# Use filename if provided as environment variable, or "foo" as default
filename=${filename-foo}

grepand () {
# disable word splitting and globbing
IFS=
set -f
if [[ -n $1 ]]
then
grep -i "$1" ${filename} | filename="" grepand "${@:2}"
else
# If there are no arguments, assume last command in pipe and print everything
cat
fi
}

grepand "$@"
0
ответ дан 22 November 2019 в 23:56

Другие вопросы по тегам:

Похожие вопросы: