Saya memiliki kode berikut yang akan menghapus garis dengan pola banana
dan 2 baris setelahnya:
sed '/banana/I,+2 d' file
Sejauh ini baik! Tapi saya perlu menghapus 2 baris sebelumnya banana
, tapi saya tidak bisa mendapatkannya dengan "tanda minus" atau apa pun (mirip dengan apa yang grep -v -B2 banana file
harus dilakukan tetapi tidak):
teresaejunior@localhost ~ > LC_ALL=C sed '-2,/banana/I d' file
sed: invalid option -- '2'
teresaejunior@localhost ~ > LC_ALL=C sed '/banana/I,-2 d' file
sed: -e expression #1, char 16: unexpected `,'
teresaejunior@localhost ~ > LC_ALL=C sed '/banana/I,2- d' file
sed: -e expression #1, char 17: unknown command: `-'
shell-script
text-processing
sed
awk
Teresa e Junior
sumber
sumber
awk '{l[m=NR]=$0}/banana/{for(i=NR-2;i<=NR;i++)delete l[i]}END{for(i=1;i<=m;i++)if(i in l)print l[i]}'
. Ini tidak efisien, jadi ini hanya petunjuk, bukan solusi.tac file | sed ... | tac
. : Psed '/banana/,+2d' file
itu juga akan berhasilawk 'tolower($0)~/bandana/{print prev[!idx];print prev[idx]} {idx=!idx;prev[idx]=$0}' filein
Karena ini adalah komentar dan bukan jawaban (sudah ada jawaban lain), saya tidak akan membahas terlalu banyak detail, tetapi intinya adalah Anda selalu memiliki dua catatan sebelumnya dalam prev [0] dan prev [1], "segar" tergantung pada iterasi mana tetapi selalu diprev[idx]
, jadi ketika Anda mencetak, Anda mencetak!idx
kemudianidx
memesan. Apapun, gantilahidx
dan masukkan catatan saat iniprev[idx]
.Jawaban:
Sed tidak mundur: setelah diproses garis, selesai. Jadi “temukan garis dan cetak garis N sebelumnya” tidak akan berfungsi sebagaimana mestinya, tidak seperti “temukan garis dan cetak garis N berikutnya” yang mudah dicangkokkan.
Jika file tidak terlalu panjang, karena Anda tampaknya tidak masalah dengan ekstensi GNU, Anda dapat menggunakan
tac
untuk membalikkan baris file.Sudut serangan lain adalah mempertahankan jendela geser di alat seperti awk. Beradaptasi dari Adakah alternatif untuk switch grep -A -B -C (untuk mencetak beberapa baris sebelum dan sesudah)? (peringatan: minimal diuji):
Pemakaian:
/path/to/script -v pattern='banana' -v before=2
sumber
sed
dapat melakukan sliding windows juga, tetapi skrip yang dihasilkan biasanya tidak terbaca sehingga lebih mudah digunakanawk
.awk
Skripnya kurang tepat; apa adanya mencetak baris kosong dan melewatkan baris terakhir. Ini tampaknya untuk memperbaikinya, tetapi mungkin tidak ideal atau benar sendiri:if (NR-before in h) { print...; delete...; }
... dan diEND
bagian:for (i in h) print h[i]
... Juga, skrip awk mencetak baris yang cocok, tetapitac/sec
versinya tidak; tapi pertanyaannya agak ambigu pada ini .. Script awk "asli", yang Anda berikan tautan, berfungsi dengan baik .. Saya menyukainya ... Saya tidak yakin bagaimana 'mod' di atas mempengaruhi hasil cetak setelah lines ...Ini cukup mudah dengan ex atau vim -e
Ekspresi berbunyi: untuk setiap baris yang berisi pisang dalam kisaran dari baris saat ini -2 ke baris saat ini, hapus.
Apa yang keren adalah bahwa rentang juga dapat berisi pencarian maju dan mundur, misalnya ini akan menghapus semua bagian file dimulai dengan baris yang mengandung apel dan diakhiri dengan baris yang mengandung oranye dan berisi baris dengan pisang:
sumber
Menggunakan "jendela geser" di
perl
:sumber
Anda dapat melakukan ini dengan cukup sederhana dengan
sed
:Saya tidak tahu mengapa ada orang yang mengatakan sebaliknya, tetapi untuk menemukan garis dan mencetak baris sebelumnya
sed
menggabungkan built-inP
rint primitive yang hanya menulis hingga\n
karakter ewline pertama dalam ruang pola.D
Elete primitif komplementer menghilangkan segmen ruang pola yang sama sebelum secara berulang mendaur ulang skrip dengan yang tersisa. Dan untuk mengatasinya, ada primitif untuk menambahkan jalurN
input ext ke ruang pola mengikuti\n
karakter ewline yang dimasukkan .Sehingga satu baris
sed
harus menjadi semua yang Anda butuhkan. Anda tinggal menggantimatch
dengan regexp apa pun Anda dan Anda emas. Itu harus menjadi solusi yang sangat cepat juga.Perhatikan juga bahwa ia akan menghitung dengan benar yang
match
mendahului yang lainmatch
sebagai pemicu untuk menghentikan output untuk dua baris sebelumnya dan juga menghentikan pencetakannya:Agar dapat bekerja untuk jumlah baris yang sewenang - wenang , yang perlu Anda lakukan adalah mendapatkan petunjuk.
Begitu:
... menghapus 5 baris sebelum pertandingan apa pun.
sumber
Menggunakan
man 1 ed
:sumber