Греп ищет два слова в строке

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

40 голосов | спросил Sebastian 27 FebruaryEurope/MoscowbFri, 27 Feb 2015 00:13:43 +0300000000amFri, 27 Feb 2015 00:13:43 +030015 2015, 00:13:43

7 ответов


53

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

В regex, который является 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
ответил Florian Diesch 27 FebruaryEurope/MoscowbFri, 27 Feb 2015 00:29:58 +0300000000amFri, 27 Feb 2015 00:29:58 +030015 2015, 00:29:58
25

Вы можете передать вывод первой команды 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 для последующих совпадений «AND».

ответил Aditya 27 FebruaryEurope/MoscowbFri, 27 Feb 2015 00:31:22 +0300000000amFri, 27 Feb 2015 00:31:22 +030015 2015, 00:31:22
19

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

awk '/lemon/ && /rice/'

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

ответил David B. 27 FebruaryEurope/MoscowbFri, 27 Feb 2015 06:49:50 +0300000000amFri, 27 Feb 2015 06:49:50 +030015 2015, 06:49:50
11

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

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

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

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

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

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

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


Внешние ссылки:
Расширенные темы Grep
Позитивный Lookahead - GREP для дизайнеров Суб>

ответил αғsнιη 27 FebruaryEurope/MoscowbFri, 27 Feb 2015 02:05:47 +0300000000amFri, 27 Feb 2015 02:05:47 +030015 2015, 02:05:47
3
grep -e foo -e goo

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

ответил netskink 24 J000000Monday17 2017, 17:46:14
1

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

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

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

ответил Gilles Maisonneuve 25 PM000000100000005431 2018, 22:51:54
0

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

 #!/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 "[email protected]"
ответил Jeff 3 FebruaryEurope/MoscowbFri, 03 Feb 2017 04:21:38 +0300000000amFri, 03 Feb 2017 04:21:38 +030017 2017, 04:21:38

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

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132