Anda dapat melakukannya sebagai berikut:
$ sed -e '
/BEGIN/,/END/!d
H;/BEGIN/h;/END/!d;g
' inp
Cara kerjanya adalah, untuk rentang garis awal/akhir, ia menyimpannya di ruang tunggu. Kemudian hapus sampai Anda memenuhi garis END. Pada titik mana kita mengingat apa yang ditahan. OTW, kami tidak mendapatkan apa-apa.HTH.
cat input |
sed '/\*\*\*\*\* BEGIN \*\*\*\*\*/,/\*\*\*\*\* END *\*\*\*\*/ p;d' |
tac |
sed '/\*\*\*\*\* END \*\*\*\*\*/,/\*\*\*\*\* BEGIN *\*\*\*\*/ p;d' |
tac
Ia bekerja dengan memiliki tac
balikkan barisnya sehingga sed
dapat menemukan kedua pembatas di kedua pesanan.
Dengan pcregrep
:
pcregrep -M '(?s)BEGIN.*?END'
Itu juga berfungsi jika BEGIN dan END berada di baris yang sama, tetapi tidak dalam kasus seperti:
BEGIN 1 END foo BEGIN 2
END
Dimana pcregrep
menangkap BEGIN 1 END
pertama , tapi bukan yang kedua.
Untuk mengatasinya, dengan awk
, Anda dapat melakukan:
awk '
!inside {
if (match($0, /^.*BEGIN/)) {
inside = 1
remembered = substr($0, 1, RLENGTH)
$0 = substr($0, RLENGTH + 1)
} else next
}
{
if (match($0, /^.*END/)) {
print remembered $0
if (substr($0, RLENGTH+1) ~ /BEGIN/)
remembered = ""
else
inside = 0
} else
remembered = remembered $0 ORS
}'
Pada masukan seperti:
a
BEGIN blah END BEGIN 1
2
END
b
BEGIN foo END
c
BEGIN
bar
END BEGIN
baz END
d
BEGIN
xxx
Ini memberi:
BEGIN blah END BEGIN 1
2
END
BEGIN foo END
BEGIN
bar
END BEGIN
baz END
Keduanya perlu menyimpan semuanya dari BEGIN hingga END berikutnya dalam memori. Jadi, jika Anda memiliki file besar yang baris pertamanya berisi BEGIN tetapi tanpa END, seluruh file akan disimpan dalam memori tanpa biaya.
Satu-satunya jalan keluar adalah memproses file dua kali, tetapi tentu saja itu hanya dapat dilakukan jika inputnya adalah file biasa (bukan pipa misalnya).