Grep pola multiline


13

Bagaimana cara mencari frasa melalui beberapa baris? Misalkan kita memiliki frasa "my ice tea" maka dapat dibungkus dengan file teks:

as js skdfh dfh djh sf my
ice tea.

grep tidak akan cocok karena ada baris baru di antaranya. Bagaimana saya mencocokkannya? Pola multiline lainnya adalahpattern1_\n_pattern2

Saya tahu cara termudah yang saya lakukan ATM hanya grep untuk satu bagian misalnya hanya es dengan bendera -A2 -B2 dan kemudian dalam output yang againg untuk misalnya teh. Tapi ini sangat membosankan. Jadi saya campur tangan tentang bagaimana Anda akan menyelesaikan ini.


Jawaban:


16

Anda dapat menginstal pcregrep(tersedia di sebagian besar repositori distro) - yang grep menggunakan perpustakaan pcre , yang tidak "Perl Regular Regular Expressions". Ini memiliki opsi baris perintah -Myang memungkinkan Anda melakukan pencarian multiline - dari halaman manual :

"Output untuk setiap pertandingan mungkin terdiri lebih dari satu baris."

Jadi kamu bisa melakukannya

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

The \sadalah spasi, yang akan cocok \ndan \rdalam mode multiline, selain karakter spasi normal. Anda juga dapat mencocokkan karakter baris baru secara langsung, sehingga Anda bisa melakukannya

pcregrep -M 'pattern1_\n_pattern2' filename

+1 bagus. tidak pernah mendengarnya, tetapi mencobanya dan itu bekerja seperti pesona!
DaveParillo

Tidak grep -Emelakukan pola pcre?
Daenyth

3
@Daenyth grep -E kebanyakan hanya berarti Anda dapat menggunakan ?, +, {, |, (, dan )seperti biasa makna regex mereka tanpa harus memiliki \ di depan, seperti yang Anda lakukan jika Anda menggunakan grep standar. Begitu grep 'hello\s\+world' filejuga dengan grep -E 'hello\s+world' file. Itu tidak melakukan PCRE. Ada grep -Puntuk ekspresi reguler perl, tetapi ini eksperimental (menurut halaman manual) dan saya pikir itu sedikit berbeda dari pcregrep ...
Hamish Downer

1
Ya, saya sedang memikirkan -Pketika saya berkata -E, tetapi saya tidak menyadari itu berbeda.
Daenyth

3

Saya mungkin akan melakukan pencarian menggunakan vim's :vimgrepperintah. Ini bekerja dengan cara yang agak mirip dengan greptetapi mendukung vim RE dan jalur.

Pada dasarnya Anda menjalankan sesuatu seperti :vimgrep 'pattern1\npattern2' path/**untuk pencarian rekursif, lalu ketik :copenuntuk membuka jendela yang lebih kecil berisi daftar kecocokan.

vimRE dapat melakukan sebagian besar semua yang dapat dilakukan PCRE, tetapi mereka berevolusi secara terpisah dari garis turunan reguler perl sehingga sebagian besar barang canggih bekerja secara berbeda. Fungsionalitas dasar mereka lebih mirip dengan RE dasar, tetapi mereka memiliki beberapa tambahan bagus yang tidak ditawarkan PCRE.

Saya tidak yakin apakah mungkin untuk :vimgrepmengeluarkan data seperti grephalnya; Saya hanya pernah mencoba menggunakannya untuk navigasi di dalam vim.

:help vimgrepdari dalam vimuntuk info lebih lanjut; :help pattern.txtuntuk info tentang vimRE; untuk info lebih lanjut tentang jalur, lihat :help wildcards.


Hati-hati - itu tidak sepenuhnya portabel karena akan berperilaku berbeda pada platform yang berbeda
Daenyth

1
@Daenyth: maksud Anda di bawah pengaruh yang berbeda .vimrc? Seharusnya lebih portabel daripada grepsehubungan dengan sistem operasi: vimtidak memiliki "rasa POSIX", dan bekerja kurang lebih identik bahkan di bawah Windows. .................................................. ........................... Mungkin saja untuk menambahkan kualifikasi untuk memastikan bahwa mis. Jumlah "sihir" yang tepat digunakan pada RE, meskipun seperti yang saya mengerti ada aturan ketat yang tidak tertulis untuk meninggalkan opsi itu sendiri.
intuited

Saya belum menggunakannya sendiri, tetapi tampaknya ia menggunakan backend yang berbeda di windows ( find.exebukan grep). Ada pertanyaan lain dalam beberapa minggu terakhir yang memiliki masalah itu.
Daenyth

1
@Daenyth: Apakah Anda memikirkan :vimgrepatau :grep? Dari :help grep: "Keuntungan dari grep internal [yaitu :vimgrep] adalah ia bekerja pada semua sistem dan menggunakan pola pencarian Vim yang kuat."
intuited

1
Ah, pasti begitu. Saya membuat keduanya bingung.
Daenyth

2

Grep hanya bekerja pada satu baris pada satu waktu, tetapi Anda dapat menggunakan awk untuk mencetak garis yang cocok dengan berbagai pola:

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

itu akan cocok dengan apa pun, bukan hanya baris baru di antara kedua pola


0

Untuk mendapatkan hasil maksimal dari unix, Anda perlu memanfaatkan pipa. Anda dapat melakukannya di dataran grepmenggunakan pipa (tidak perlu tee):

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

Yang menurut saya tidak membosankan.


Saya pikir ini rawan kesalahan, karena antara pattern1 dan pattern2 dapat ada pattern3 yang mungkin tidak seperti yang Anda cari. Jadi, Anda harus mengontrol setiap hit secara manual.
matematika
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.