Cara memilih kemunculan pertama antara dua pola termasuk mereka


27

Bagaimana saya bisa memilih kejadian pertama antara dua pola termasuk mereka. Lebih disukai menggunakan sedatau awk.

Saya sudah:

text
something P1 something
content1
content2
something P2 something
text
something P1 something
content3
content4
something P2 something
text

Saya ingin kemunculan pertama garis antara P1 dan P2 (termasuk garis P1 dan garis P2):

something P1 something
content1
content2
something P2 something

Jawaban:


22
sed '/P1/,/P2/!d;/P2/q'

... akan melakukan pekerjaan dengan dmudah dengan menghapus semua garis yang !tidak termasuk dalam rentang, kemudian qmenggunakan saat pertama kali bertemu ujung rentang. Itu tidak gagal untuk P2 sebelum P1, dan itu tidak memerlukan sintaks khusus GNU untuk menulis secara sederhana.


Luar biasa! Jauh lebih baik dari milikku.
muru

1
@muru - Sering kali lebih mudah untuk menghindari liuk jika Anda mencoba menargetkan cetak otomatis - biarkan siklusnya bekerja untuk Anda. Begitulah kebiasaan saya. Saya pikir itu mungkin lebih baik digambarkan sebagai prune vs metode pilih - Saya cenderung akhirnya meniadakan pola daripada mencarinya.
mikeserv

Ini akan hang saat memproses fileSize besar.
Brain90

@ Brain90 - tidak boleh. jika Anda dapat dengan benar mereproduksi keluhan Anda, Anda harus menghubungi pengelola sed... itu adalah bug yang sedAnda jalankan, dan bukan dalam skrip di atas.
mikeserv

1
@ mikeserv saya tidak akan mengatakannya jika saya tidak. Kekhawatiran Anda tentang apakah saya peduli pada beberapa karakter atau tidak aneh: Saya mengamati bahwa ekspresi sed bekerja dengan dan tanpa /P2/qpada sistem saya; itu dia. Saya ingin tahu tentang sesuatu dan ingin membagikan apa yang saya temukan.
Alexej Magura

8

dengan awk

awk '/P1/{a=1};a;/P2/{exit}' file
something P1 something
content1
content2
something P2 something

8

Di sed:

sed -n '/P1/,/P2/p; /P2/q'
  • -nmenekan pencetakan default, dan Anda mencetak garis di antara rentang alamat yang cocok menggunakan pperintah.
  • Biasanya ini akan cocok dengan kedua bagian, sehingga Anda keluar ( q) ketika yang pertama P2cocok.

Ini akan gagal jika ada yang P2datang sebelumnya P1. Untuk menangani kasus itu, cobalah:

sed -n '/P1/,/P2/{p; /P2/q}'

1
Saya tidak setuju; Jawaban mikeserv tidak lebih baik dari jawaban Anda.
G-Man Mengatakan 'Reinstate Monica'

@ g-man - pshaw. tetapi saya hanya memikirkan hal yang sama.
mikeserv

1
@man - tidak sekarang saya mengerti. tambang jauh lebih baik. tidak ada {stack}!
mikeserv

1

Jika Anda ingin melewati pola sendiri, ini awkversinya:

awk '/P2/ {exit} /P1/ {f=1; next} f' file

Bekerja untukku. Bisakah Anda menambahkan lebih banyak info tentang cara kerja perintah?
0xAffe

1

awkSolusi yang lebih sederhana (semacam setengah antara jawaban iruvar dan  jawaban muru , tetapi tidak menggunakan variabel):

awk '/P1/,/P2/ { print }  /P2/ { exit }'

dan, seperti yang dicatat muru, jika P2 pertama muncul sebelum P1 pertama, ini tidak akan mencetak apa pun.

Tentu saja, jika Anda ingin mencetak semua rentang P1-P2:

something P1 something
content1
content2
something P2 something
something P1 something
content3
content4
something P2 something

biarkan exitbagian:

awk '/P1/,/P2/ { print }'

1
awk '/P1/,/P2/{print;f=1} f&&/P2/{exit}' data

Keluar segera setelah dicetak, bukan sebelumnya.


0

Untuk melewati pola itu sendiri, dan hanya menampilkan blok pencocokan pertama dalam sed GNU tunggal:

sed -nre '/STARTPATTERN/ {:a;n;/ENDPATTERN/{b;};p;ba}' file
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.