Як підключити декілька візерунків у кількох лініях?


19

Якщо бути точним

Some text
begin
Some text goes here.
end
Some more text

і я хочу витягти весь блок, який починається від "починати" до "кінця".

з awk ми можемо зробити так, як awk '/begin/,/end/' text.

Як робити греп?


Відповіді:


14

Оновлено 18 листопада 2016 року (оскільки поведінка grep змінена: grep з параметром -P тепер не підтримує ^і $закріплює [на Ubuntu 16.04 з ядром v: 4.4.0-21-generic]) ( неправильне (не) виправлення )

$ grep -Pzo "begin(.|\n)*\nend" file
begin
Some text goes here.  
end

Примітка: для інших команд просто замініть якір '^' і '$' на якір нового рядка '\n' ______________________________

З командою grep:

grep -Pzo "^begin\$(.|\n)*^end$" file

Якщо ви не бажаєте включати шаблони "почати" і "закінчити" в результаті, використовуйте grep з підтримкою Lookbehind і Lookahead.

grep -Pzo "(?<=^begin$\n)(.|\n)*(?=\n^end$)" file

Також ви можете використовувати \Kсповіщення замість твердження Lookbehind.

grep -Pzo "^begin$\n\K(.|\n)*(?=\n^end$)" file

\Kваріант ігнорувати все перед узгодженням шаблону та ігнорувати сам шаблон.
\nвикористовується для уникнення друку порожніх рядків з виводу.

Або як @AvinashRaj припускає, що тут є простий легкий греп:

grep -Pzo "(?s)^begin$.*?^end$" file

grep -Pzo "^begin\$[\s\S]*?^end$" file

(?s)говорить grep, щоб дозволити крапці відповідати символам нового рядка.
[\s\S]відповідає будь-якому символу, який є або пробілом, або непробілом.

А їх вихід без включення "start" і "end" такий:

grep -Pzo "^begin$\n\K[\s\S]*?(?=\n^end$)" file # or grep -Pzo "(?<=^begin$\n)[\s\S]*?(?=\n^end$)"

grep -Pzo "(?s)(?<=^begin$\n).*?(?=\n^end$)" file

дивіться повний тест всіх команд тут ( застаріле, як поведінка grep з параметром -P змінено )

Примітка:

^вкажіть початок рядка і $вкажіть кінець рядка. вони додаються до "початку" та "кінця", щоб їх відповідати, якщо вони опинилися в одній лінії.
У двох командах я втік, $тому що він також використовує для "Заміна команди" ( $(command)), що дозволяє вивести команду на заміну імені команди.

Від людини греп:

-o, --only-matching
      Print only the matched (non-empty) parts of a matching line,
      with each such part on a separate output line.

-P, --perl-regexp
      Interpret PATTERN as a Perl compatible regular expression (PCRE)

-z, --null-data
      Treat the input as a set of lines, each terminated by a zero byte (the ASCII 
      NUL character) instead of a newline. Like the -Z or --null option, this option 
      can be used with commands like sort -z to process arbitrary file names.

змінити греп, як ніби grep -Pzo "(?<=begin\n)(.|\n)*(?=\nend)" fileне друкувати \nсимволи, які існують у рядку, починаються.
Авінаш Радж

Використовуйте модифікатор DOTALL, щоб зробити крапку навіть для символів нового рядкаgrep -Pzo "(?s)begin.*?end" file
Avinash Raj

Або просто,grep -Pzo "begin[\s\S]*?end" file
Авінаш Радж

1
Ситуація не працює. Це призводить до помилки: grep: ein nicht geschütztes ^ oder $ wird mit -Pz nicht unterstütztПереклад помилки виглядає приблизно так:grep: a not protected ^ or $ is not supported with -Pz
musbach

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

2

Якщо ваш grepне підтримує синтаксис perl ( -P), ви можете спробувати приєднатись до рядків, узгоджуючи шаблон, а потім знову розгорнути рядки, як показано нижче:

$ tr '\n' , < foo.txt | grep -o "begin.*end" | tr , '\n'
begin
Some text goes here.
end
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.