Cari string dan cetak semuanya sebelum dan sesudah dalam rentang


9

Saya punya file ini:

sometext1{
string1
}

sometext2{
string2
string3
}

sometext3{
string4
string5
string6
}

Saya ingin mencari file ini untuk string tertentu dan mencetak semuanya sebelum string ini hingga pembukaan {dan semuanya setelah string ini hingga penutupan }. Saya mencoba untuk mencapai ini dengan sed tetapi jika saya mencoba untuk mencetak segala sesuatu dalam kisaran /{/,/string2/misalnya cetak sed ini:

sometext1{
string1
}

sometext2{
string2
sometext3{
string4
string5
string6
}

Jika saya mencari string "string2" saya perlu output menjadi:

sometext2{
string2
string3
}

Terima kasih.


Nah, sekarang saya menemukan bahwa saya perlu nomor baris ouput di file asli untuk menghapusnya nanti. Saya mencoba mengubah perintah yang disediakan @mikeserv tanpa hasil, saya agak bingung dengan fungsi hold sed.
rodrigo

baik, ya ampun, rodrigo, Anda tidak memberi tahu siapa pun kecuali diri Anda sendiri. itu bisa dilakukan, tetapi paling baik dilakukan seperti grep -n '' <infile | sed .... sedPerintah - perintah perlu dimodifikasi; khususnya bit /alamat /yang mencari ^jangkar top-of-line. Jadi, jika Anda menggunakan jawaban saya Anda mungkin bisa melakukan: grep -n '' | sed 'H;/{$/h;/^[^:]*:}/x;/{\n.*PATTERN/!d'. Semua baris output akan diawali dengan nomor baris file asli diikuti oleh titik dua seperti 1:sometext1{\n2:string1dan seterusnya. sedakan menyaring hanya apa yang akan disaring sebelumnya, kecuali bahwa setiap jalur output terbuka dengan angka.
mikeserv

Jawaban:


9

Berikut ini dua perintah. Jika Anda menginginkan perintah yang memotong hingga .*{$baris terakhir secara berurutan (seperti yang dilakukan @don_crissti ed), Anda dapat melakukannya:

sed 'H;/{$/h;/^}/x;/{\n.*PATTERN/!d'

... yang bekerja dengan menambahkan setiap baris ke Hruang lama mengikuti \nkarakter ewline, menimpa hruang lama untuk setiap baris yang cocok {$, dan menukar hruang lama dan pola untuk setiap baris yang cocok ^}- dan dengan demikian menyiram buffernya.

Ini hanya mencetak garis yang cocok dengan garis {lalu \ndan kemudian PATTERNdi beberapa titik - dan itu hanya terjadi segera setelah buffer swap.

Ini menghilangkan setiap baris dalam serangkaian {$pertandingan hingga yang terakhir dalam urutan, tetapi Anda bisa mendapatkan semua yang inklusif seperti:

sed '/PATTERN.*\n/p;//g;/{$/,/^}/H;//x;D'

Apa yang dilakukannya adalah menukar pola dan hruang lama untuk setiap ...{$.*^}.*urutan, menambahkan semua baris dalam urutan ke Hruang lama mengikuti \nkarakter ewline, dan Dmenghapus hingga \nkarakter ewline pertama yang muncul di ruang pola untuk setiap siklus baris sebelum memulai kembali dengan yang tersisa.

Tentu saja, satu-satunya waktu yang pernah diperoleh \ngaris dalam ruang pola adalah ketika baris input cocok ^}- akhir rentang Anda - dan ketika itu memutarkan kembali skrip pada kesempatan lain, ia hanya menarik baris input berikutnya seperti biasa.

Ketika PATTERNditemukan dalam ruang pola yang sama dengan \newline, ia mencetak lot sebelum menimpanya ^}lagi (sehingga dapat mengakhiri rentang dan menyiram buffer) .

Diberikan file input ini (terima kasih) :

sometext1{
string1
}

sometext2{
PATTERN
string3
}

sometext3{
string4
string5
string6
}

Header{
sometext4{
some string

string unknown

here's PATTERN and PATTERN again
and PATTERN too
another string here
}
}

Cetakan pertama:

sometext2{
PATTERN
string3
}
sometext4{
some string

string unknown

here's PATTERN and PATTERN again
and PATTERN too
another string here
}

... dan yang kedua ...

sometext2{
PATTERN
string3
}
Header{
sometext4{
some string

string unknown

here's PATTERN and PATTERN again
and PATTERN too
another string here
}

@don_crissti - Saya tidak tahu. Ini hanya membatasi urutan untuk garis yang dimulai dengan }. Ini bisa bermanfaat untuk seperti ... open{\nsub;\n{ command; }\n}; close- tapi saya tidak yakin apa yang terjadi di sini ...
mikeserv

Hai @mikeserv - Saya punya pertanyaan serupa yang diajukan di sini unix.stackexchange.com/questions/232509/… , solusi Anda berfungsi pada file kecil, tapi saya punya file besar dan saya mendapat "Tahan ruang yang diluap." pesan eror. Setiap kesempatan yang Anda tahu, bagaimana saya bisa menyelesaikan ini? Terima kasih banyak
Narayan Akhade

@NarayanAkhade - no. bukan tanpa perombakan. kecuali ... apakah ada bentangan input besar yang tidak berisi {...}blok? Jika itu masalahnya dan Anda menggunakan solusi pertama maka Anda bisa melakukannya /{$/,/^}/Hdi awal, bukan hanya H. Tetapi jika Anda juga mencoba solusi kedua dan masih mengalami kesalahan yang sama itu tidak akan membantu karena yang sudah melakukannya. Dan jangan diskon edjuga. don mendapat jawaban yang sangat baik di sini, dan eddapat diterapkan untuk menggunakan file buffer sementara dengan sangat sederhana, yang seharusnya mencegah mem buffer overruns.
mikeserv

6

Inilah solusi dengan ed:

ed -s filename <<< $'g/PATTERN/?{?,/}/p\nq\n'

itu adalah:

g/PATTERN/     # mark each line matching PATTERN  
?{?,/}/p       # for each marked line, print all lines from the previous { up to the next }  
q              # quit editor

Ini mengasumsikan hanya ada satu baris dengan PATTERNantara setiap pasangan { }jika tidak, Anda akan mendapatkan hasil duplikat untuk setiap baris tambahan dengan PATTERNdi dalam blok yang sama.
Ini akan berfungsi untuk beberapa yang { }berisi satu baris yang cocok PATTERNmisalnya untuk file uji dengan PATTERNdi dua bagian yang berbeda:

sometext1{
string1
}

sometext2{
PATTERN
string3
}

sometext3{
string4
string5
string6
}

Header{
sometext4{
some string

string unknown

here's PATTERN again

another string here
}
}

berlari

ed -s sample <<< $'g/PATTERN/?{?,/}/p\nq\n'

output:

sometext2{
PATTERN
string3
}
sometext4{
some string

string unknown

here's PATTERN again

another string here
}

Saya mengambil banyak dari ini, sebenarnya! Terima kasih banyak!
mikeserv

Aku bahkan tidak tahu perintah ini ada. Terima kasih
rodrigo

4

Dengan pcregrep:

pcregrep -M '(?s)\{[^}]*PATTERN.*?\}'

Atau dengan GNU grepasalkan input tidak mengandung byte NUL:

grep -Poz '.*(?s)\{[^}]*PATTERN.*?\}'

0
$ awk 'BEGIN{RS="\n\n"; FS="[{}]"} {if ($2 ~ /string4/) {print $2}}' t1.txt
string4
string5
string6

dimana:

  • string4 -> string untuk dicocokkan
  • t1.txt -> berisi konten file yang disebutkan dalam kueri

-2

sed -n '/ string / p' nama file

-n ketika ditambahkan ke perilaku standar sed sed suppressed pernyataan ini mungkin tidak memberikan apa yang Anda inginkan, tetapi seharusnya hanya menggeser string

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.