Я намагався знайти спосіб відфільтрувати рядок, в якому є слово "лимон" та "рис". Я знаю, як знайти "лимон" або "рис", але не їх два. Їм не потрібно бути поруч з одним, лише один і той же рядок тексту.
Я намагався знайти спосіб відфільтрувати рядок, в якому є слово "лимон" та "рис". Я знаю, як знайти "лимон" або "рис", але не їх два. Їм не потрібно бути поруч з одним, лише один і той же рядок тексту.
Відповіді:
"Обоє в одному рядку" означають "рис", за яким слідують випадкові символи, а потім "лимон" або навпаки ".
У регулярному вираженні це 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
за замовчуванням до базового регексу, де \|
АБО
grep
"Російська сторінка", 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 для подальших матчів "AND".
опція grep з -P
(Perl-Compatibility) опцією та позитивним виразним виглядом(?=(regex))
:
grep -P '(?=.*?lemon)(?=.*?rice)' infile
або ви можете використовувати нижче, замість цього:
grep -P '(?=.*?rice)(?=.*?lemon)' infile
.*?
кошти , відповідні будь-які символи , .
які входження нуль або більше разів , *
поки вони НЕ є обов'язковими з подальшим малюнком ( rice
або lemon
). ?
Робить все Факультативно , перш ніж він (означає нуль або один раз за все відповідає .*
)(?=pattern)
: Позитивний Lookahead: Позитивна конструкція lookahead - це пара круглих дужок, за круглими дужками, за якими слідує знак питання та знак рівності.
Таким чином, це поверне всі рядки з містить lemon
і rice
в, і в довільному порядку. Також це дозволить уникнути використання |
s та подвоєних grep
s.
Зовнішні посилання:
Розширені теми 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.
Ось сценарій для автоматизації рішення греп-трубопроводів:
#!/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
його, який легко порушується