Birden çok satırda birden çok desen için nasıl grep yapabilirim?


Yanıtlar:


14

18 Kasım 2016'da güncellendi (grep davranışı değiştiği için: -P parametresiyle grep artık desteklemiyor ^ve $[vunt ile Ubuntu 16.04'te: 4.4.0-21-jenerik]) ( yanlış (olmayan) düzeltme )

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

not: diğer komutlar için sadece '^' & '$' bağlantılarını yeni hat bağlantılarıyla değiştirin '\n' ______________________________

Grep komutuyla:

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

Sonuçta "begin" ve "end" kalıplarını dahil etmek istemiyorsanız, Lookbehind ve Lookahead desteği ile grep kullanın.

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

Ayrıca \KLookbehind iddiası yerine bildir özelliğini de kullanabilirsiniz .

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

\Kseçeneği, desen eşleşmesinden önce her şeyi yoksay ve desenin kendisini yoksay.
\nboş satırların çıktıdan yazdırılmasını önlemek için kullanılır.

Veya @AvinashRaj'ın önerdiği gibi aşağıdaki gibi basit kolay grepler vardır:

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

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

(?s)grep'e noktanın yeni satır karakterleriyle eşleşmesine izin vermesini söyler.
[\s\S]boşluk veya boşluk olmayan herhangi bir karakterle eşleşir.

Ve "begin" ve "end" içermeden çıktıları aşağıdaki gibidir:

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

burada tüm komutların tam testine bakın ( -P parametresiyle grep davranışı değiştiğinden eskimiş )

Not:

^bir satırın başlangıcını ve bir satırın $sonunu işaret eder. bunlar bir satırda yalnızlarsa eşleşmeleri için "başlangıç" ve "bitiş" etrafına eklenirler.
İki komutta $da kaçtım çünkü $(command)komutun çıktısının komut adının yerine geçmesine izin veren "Command Substitution" ( ) işlevini de kullanıyor .

Adam grep'ten:

-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.

satırında var olan karakteri grep -Pzo "(?<=begin\n)(.|\n)*(?=\nend)" fileyazdırmamak için grep değiştirin \n.
Avinash Raj

Hatta newline karakterleri ile eşleştirmek için nokta yapmak için DOTALL değiştiricisini kullanıngrep -Pzo "(?s)begin.*?end" file
Avinash Raj

Veya Basitçe,grep -Pzo "begin[\s\S]*?end" file
Avinash Raj

1
Siólution çalışmıyor. Bir hata üretir: Hatanın grep: ein nicht geschütztes ^ oder $ wird mit -Pz nicht unterstütztçevirisi grep: a not protected ^ or $ is not supported with -Pz
şuna

1
Evet, biliyorum, bu senin cevabında. Eminim bunu yayınladığınızda işe yaradı, ama bugün tekrar deneyin. Davranışı grepdeğişmiş gibi görünüyor.
terdon

2

Durumda senin grepperl sözdizimi (desteklemez -P), sen, çizgiler katılmadan desen eşleştirme, daha sonra aşağıdaki gibi tekrar hatları genişleyen deneyebilirsiniz:

$ tr '\n' , < foo.txt | grep -o "begin.*end" | tr , '\n'
begin
Some text goes here.
end
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.