Bagaimana cara saya menerima beberapa pola pada banyak baris?

Jawaban:

14

Diperbarui 18-Nov-2016 (karena perilaku grep berubah: grep dengan -P parameter sekarang tidak mendukung ^dan $berlabuh [di Ubuntu 16,04 dengan kernel v: 4.4.0-21-generic]) ( memperbaiki salah (non-) memperbaiki )

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

Catatan: untuk perintah lain, ganti saja jangkar '^' & '$' dengan jangkar baris baru '\n' ______________________________

Dengan perintah grep:

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

Jika Anda mau, jangan sertakan pola "mulai" dan "akhiri" dalam hasilnya, gunakan grep dengan dukungan Lookbehind dan Lookahead.

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

Anda juga dapat menggunakan \Knotifikasi alih-alih pernyataan Lookbehind.

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

\Kopsi abaikan semuanya sebelum pencocokan pola dan abaikan pola itu sendiri.
\ndigunakan untuk menghindari pencetakan baris kosong dari output.

Atau seperti @AvinashRaj menyarankan ada grep mudah sederhana sebagai berikut:

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

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

(?s)memberitahu grep untuk mengizinkan titik untuk mencocokkan karakter baris baru.
[\s\S]cocok dengan karakter apa pun yang berupa spasi putih atau non-spasi putih.

Dan output mereka tanpa termasuk "mulai" dan "akhir" adalah sebagai berikut:

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

lihat tes lengkap dari semua perintah di sini ( dari tanggal sebagai perilaku grep dengan parameter -P berubah )

catatan:

^arahkan awal suatu garis dan $arahkan ujung suatu garis. ini ditambahkan ke sekitar "awal" dan "akhir" untuk mencocokkan mereka jika mereka sendirian dalam satu baris.
Dalam dua perintah saya melarikan diri $karena ia juga menggunakan untuk "Pergantian Perintah" ( $(command)) yang memungkinkan output dari suatu perintah untuk mengganti nama perintah.

Dari man grep:

-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.
αғsнιη
sumber
ubah grep Anda grep -Pzo "(?<=begin\n)(.|\n)*(?=\nend)" fileagar tidak mencetak \nkarakter yang ada pada baris begin.
Avinash Raj
Gunakan pengubah DOTALL untuk membuat titik untuk mencocokkan bahkan karakter baris barugrep -Pzo "(?s)begin.*?end" file
Avinash Raj
Atau Sederhananya,grep -Pzo "begin[\s\S]*?end" file
Avinash Raj
1
Solusi tidak bekerja. Ini menghasilkan kesalahan: grep: ein nicht geschütztes ^ oder $ wird mit -Pz nicht unterstütztTerjemahan kesalahan adalah sesuatu seperti:grep: a not protected ^ or $ is not supported with -Pz
musbach
1
Ya, saya tahu, itulah jawaban Anda. Saya yakin itu berhasil ketika Anda memposting ini, tetapi coba lagi hari ini. Perilaku grepnampaknya telah berubah.
terdon
2

Jika Anda greptidak mendukung sintaks perl ( -P), Anda dapat mencoba menggabungkan garis, mencocokkan pola, lalu memperluas garis lagi seperti di bawah ini:

$ tr '\n' , < foo.txt | grep -o "begin.*end" | tr , '\n'
begin
Some text goes here.
end
kenorb
sumber