Греп багатолінійний візерунок


13

Як шукати фразу через кілька рядків? Напр. Дозволяє мати фразу "мій чай з льодом", то вона може бути загорнута у текстові файли:

as js skdfh dfh djh sf my
ice tea.

grep не буде відповідати, оскільки між ними є новий рядок. Як я можу відповідати цим? Ще одна мультилінійна схемаpattern1_\n_pattern2

Я знаю, що найпростішим способом я роблю банкомат - це лише гребінь на одну частину, наприклад, просто лід із прапором -A2 -B2, а потім у цьому виході, наприклад, чай. Але це дуже нудно. Тож я зацікавлений у тому, як би ви вирішили це.


Відповіді:


16

Ви можете встановити pcregrep(доступний у більшості дистрибутивів дистрибутива) - що є грепом за допомогою бібліотеки pcre , яка робить "Perl сумісні регулярні вирази". У ньому є опція командного рядка, -Mяка дозволяє здійснювати багаторядковий пошук - зі сторінки man :

"Вихід для будь-якої однієї відповідності може складатися з декількох рядків."

Так ви могли зробити

pcregrep -M 'my\s+ice\s+tea' filename

\sЄ прогалиною, який буде відповідати \nі \rв багаторядковому режимі, в доповненні до звичайних символів пробілів. Ви також можете безпосередньо відповідати символу нової лінії, щоб ви могли це зробити

pcregrep -M 'pattern1_\n_pattern2' filename

+1 приємно. ніколи не чула про це, але спробувала це, і це працює як шарм!
DaveParillo

Не grep -Eробить шаблонів pcre?
Daenyth

3
@Daenyth Grep -E в основному просто означає , що ви можете використовувати ?, +, {, |, (, і )як їх звичайний регулярний вираз сенсу без необхідності мати \ попереду, як ви робите , якщо ви використовуєте стандартний Grep. Так що grep 'hello\s\+world' fileеквівалентно grep -E 'hello\s+world' file. Це не робить PCRE. Існує grep -Pрегулярний вираз Perl, але він експериментальний (за даними сторінки людини), і я думаю, він трохи відрізняється від pcregrep ...
Хаміш Даунер

1
Так, я думав, -Pколи сказав -E, але не розумів, що це інакше.
Daenyth

3

Я б, ймовірно, здійснив пошук за допомогою команди vim' :vimgrep. Це працює таким чином, як приблизно подібний до способу, grepале підтримує vim REs та шляхи.

В основному ви запускаєте щось на зразок :vimgrep 'pattern1\npattern2' path/**рекурсивного пошуку, а потім наберіть, :copenщоб відкрити менше вікно, що містить список збігів.

vimЗНО можуть робити в основному все, що може PCRE, але вони еволюціонували окремо від лінії регулярного виразу Perl, тому більшість вдосконалених матеріалів працює інакше. Їх основна функціональність більше схожа на основні RE, але вони мають кілька чудових доповнень, які PCRE не пропонують.

Я не впевнений, чи можна :vimgrepвиплюнути дані, як grepце робиться; Я лише намагався використовувати його для навігації всередині vim.

:help vimgrepзсередини vimдля отримання додаткової інформації; :help pattern.txtдля інформації про vimПЕ; Детальніше про шляхи див :help wildcards.


Будьте уважні - це не зовсім портативно, оскільки він буде вести себе по-різному на різних платформах
Daenyth

1
@Daenyth: ти маєш на увазі під впливом різних .vimrc? Він повинен бути більш портативним, ніж grepвідносно операційної системи: vimне має "смаку POSIX" і працює більш-менш однаково навіть під Windows. .................................................. ........................... Можливо додати кваліфікатори для того, щоб, наприклад, потрібна кількість "магії" використовувалася на ЗНО наскільки я розумію, існує суворе неписане правило, щоб залишити цю опцію чорт у спокої.
інтуїтивно

Я сам його не використовував, але, мабуть, він використовує інший бекенд у Windows ( find.exeзамість grep). Протягом останніх декількох тижнів виникло ще одне питання, що стосувався цього питання.
Daenyth

1
@Daenyth: Ви думаєте :vimgrepчи :grep? З :help grep: "Перевага внутрішнього grep [тобто :vimgrep] полягає в тому, що він працює у всіх системах і використовує потужні схеми пошуку Vim."
інтуїтивно

1
Ах, так воно і повинно бути. Я заплутався у двох.
Daenyth

2

Grep працює лише на одному рядку, але ви можете використовувати awk для друку ліній, що відповідають різному шаблону:

cat file | awk '/foo/,/bar/'

це відповідало б будь-чому, а не лише новим рядкам між двома моделями


0

Щоб отримати максимальну користь від Unix, вам потрібно скористатися трубами. Зробити це можна просто, grepвикористовуючи труби (не потрібно трійника):

$ grep -A1 "pattern1" file.txt |  grep "pattern2"

Що б я не вважав нудним.


Я думаю, що це схильність до помилок, оскільки між pattern1 та pattern2 може існувати pattern3, який може бути не тим, що ви шукаєте. Таким чином, ви повинні контролювати кожен удар вручну.
математика
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.