Cetak garis antara (dan tidak termasuk) dua pola

13

Saya akan mengirimkan formulir menggunakan cURL, di mana beberapa konten berasal dari file lain, dipilih menggunakan sed

Jika param1pola pencocokan baris dari file lain menggunakan sed, perintah di bawah ini akan berfungsi dengan baik:

curl -d param1="$(sed -n '/matchpattern/p' file.txt)" -d param2=value2 http://example.com/submit

Sekarang, pergilah ke masalah. Saya ingin hanya menampilkan teks di antara 2 pola yang cocok tidak termasuk pola yang cocok itu sendiri.

Katakanlah file.txtmengandung:

Bla bla bla
firstmatch
It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.
secondmatch
The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English.

Saat ini, banyak sedperintah "antara 2 pola yang cocok" tidak akan dihapus firstmatchdan secondmatch.

Saya ingin hasilnya menjadi:

It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.
lokomika
sumber
stackoverflow.com/questions/17988756/…
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

Jawaban:

15

Inilah salah satu cara Anda bisa melakukannya:

sed '1,/firstmatch/d;/secondmatch/,$d' 

Dijelaskan: Dari baris pertama ke baris yang cocok dengan firstmatch , hapus. Dari baris yang cocok dengan secondmatch ke baris terakhir, hapus.

Jukka Matilainen
sumber
6

Dalam awk:

awk '
  $1 == "secondmatch" {print_me = 0}
  print_me {print}
  $1 == "firstmatch {print_me = 1}
'
glenn jackman
sumber
Di sini tentang kecepatan: unix.stackexchange.com/a/194662/16920
Léo Léopold Hertz 준영
Bagaimana dengan kecepatannya?
glenn jackman
Saya pikir SED di sini lebih unggul dibandingkan dengan AWK pada waktunya.
Léo Léopold Hertz 준영
5

sedSolusi lain akan gagal jika firstmatchterjadi pada baris 1 1 .

Sederhanakan, gunakan rentang tunggal dan regex 2 kosong :
cetak semuanya dalam rentang itu, tidak termasuk ujung rentang (pencetakan otomatis dinonaktifkan) 3 :

sed -n '/firstmatch/,/secondmatch/{//!p;}' infile

atau, lebih pendek, hapus semua yang tidak ada dalam rentang itu dan hapus juga kisaran yang berakhir:

sed '/firstmatch/,/secondmatch/!d;//d' infile


1: Alasannya adalah bahwa jika alamat kedua adalah regexp, maka memeriksa kecocokan akhir akan dimulai dengan garis mengikuti garis yang cocok dengan alamat pertama .
Oleh karena itu, /firstmatch/tidak pernah dievaluasi untuk baris pertama input, sedhanya akan menghapusnya karena cocok dengan nomor baris 1,/RE/dan beralih ke baris 2 di mana ia memeriksa apakah baris cocok/firstpattern/

2: Ketika REGEX kosong (yaitu //) sedberperilaku seolah-olah REGEX terakhir yang digunakan dalam perintah terakhir diterapkan (baik sebagai alamat atau sebagai bagian dari perintah pengganti) ditentukan.

3: ;}sintaksnya adalah untuk sedimplementasi modern ; dengan yang lebih lama gunakan baris baru, bukan titik koma atau misalnya ekspresi terpisahsed -n -e '/firstmatch/,/secondmatch/{//!p' -e '}' infile

don_crissti
sumber
Bisakah Anda menjelaskan apa yang //sedang dilakukan (di dalam {…})?
G-Man Mengatakan 'Reinstate Monica'
Terima kasih, tetapi Anda jatuh ke dalam perangkap saya. Saya tahu itu //berarti ungkapan reguler terakhir yang digunakan; dari semua yang saya baca, itu seharusnya /secondmatch/. Saya telah memverifikasi melalui pengujian bahwa perintah Anda berfungsi, dan saya menyimpulkan bahwa itu berfungsi sebagai /firstmatch|secondmatch/(yang telah Anda konfirmasi), tetapi saya tidak dapat menemukan dokumentasi apa pun (bahkan dokumen POSIX yang Anda tautkan ke atau GNU manual sed ) yang menjelaskan perilaku ini. ... (Lanjutan)
G-Man Says 'mengembalikan Monica'
(Lanjutan) ... Menghibur eksperimen: (I) Dalam sed: (1) Jika saya melakukannya /first/,4, maka //bertindaklah seperti /first/. (2) Jika saya melakukannya 2,/second/, maka //mendapat kesalahan "tidak ada ekspresi reguler sebelumnya". (Saya menemukan ini kegagalan mencolok untuk mengikuti perilaku yang ditentukan.) (3) Menambahkan --posixtidak mengubah salah satu di atas. (II) Dalam program lain: (4) Dalam vi, setelah /first/,/second/, //tindakan seperti /second/(dan bentuk lain juga merupakan implementasi rasional dari aturan yang didokumentasikan). … (Lanjutan)
G-Man Mengatakan 'Reinstate Monica'
(Lanjutan) ... (5)  awktampaknya tidak memiliki gagasan tentang "RE terakhir yang digunakan"; //mengacu pada non-karakter sebelum atau setelah karakter apa pun. (Saya mengundang Anda untuk mencoba echo -- | awk '{ gsub(//, "cha"); print }'.)
G-Man Mengatakan 'Reinstate Monica'
Jadi, Anda membaca "REGEX terakhir yang digunakan dalam perintah terakhir" sebagai "REGEX terakhir yang digunakan dalam perintah terakhir" dan Anda (dengan benar) menebak artinya /first|second/. Beruntungnya kamu. Saya menyebutkan program lain untuk menunjukkan bahwa ini bukan konvensi regex seluruh sistem. Siapa pun yang menambahkannya sedtidak perlu menambahkannya vim, di mana itu akan masuk akal. :-) ⁠
G-Man Mengatakan 'Reinstate Monica'