Я пытался найти способ отфильтровать строку, в которой есть слова «лимон» и «рис». Я знаю, как найти «лимон» или «рис», но не их обоих. Они не должны быть рядом друг с другом, просто одна и та же строка текста.
Я пытался найти способ отфильтровать строку, в которой есть слова «лимон» и «рис». Я знаю, как найти «лимон» или «рис», но не их обоих. Они не должны быть рядом друг с другом, просто одна и та же строка текста.
Ответы:
«Оба на одной строке» означает «рис», за которым следуют случайные символы, за которыми следует «лимон» или наоборот ».
В регулярном выражении это 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 rice
находит строки, содержащие rice
. Он подается в grep lemon
который будут только строки, содержащие лимон .. и так далее. Принимая во внимание, что ФП - а также ваши предыдущие ответы - разрешают любой из [рис | лимон | курица]
|
нужно сбежать grep
? Спасибо!
egrep
использует расширенное регулярное выражение, где |
понимается как логика ИЛИ. grep
по умолчанию используется базовое регулярное выражение, где \|
OR
grep
man-странице, egrep
устарела и должна быть заменена на grep -E
. Я взял на себя свободу редактировать ответ соответственно.
Вы можете направить вывод первой команды 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 lemon
This line contains both lemon and rice.
This line also contains both rice and lemon.
Мы получаем только те строки, где оба шаблона совпадают. Вы можете расширить это и передать вывод в другую команду grep для дальнейших совпадений «И».
grep с -P
(Perl-Compatibility) опцией и регулярным регулярным выражением(?=(regex))
:
grep -P '(?=.*?lemon)(?=.*?rice)' infile
или вы можете использовать ниже, вместо этого:
grep -P '(?=.*?rice)(?=.*?lemon)' infile
.*?
средства , соответствующие любые символы , .
которые вхождения ноль или более раз , *
пока они не являются обязательными с последующим рисунком ( rice
или lemon
). Он ?
делает все необязательным перед ним (означает ноль или один раз из всего совпадения .*
)(?=pattern)
: Positive Lookahead: положительная конструкция lookahead представляет собой пару круглых скобок, за открывающей скобкой следует знак вопроса и знак равенства.
Таким образом, это вернет все строки с содержит как lemon
и rice
в случайном порядке. Также это позволит избежать использования |
s и удвоенных grep
s.
Внешние ссылки:
Advanced Grep Темы Positive Lookahead - GREP для дизайнеров
Если мы признаем, что предоставление ответа, который не 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 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 "$@"
eval
разбирать ее, что легко ломается