Sed: Ganti pola di setiap baris kedua?

10

Apakah ada cara untuk mengatakan seduntuk mengganti pola pada setiap kejadian kedua? Atau setidaknya di setiap baris kedua? (Tentu mungkin dengan skrip, tapi saya bertanya pada diri sendiri apakah sedbisa melakukannya).

Edit

saya menemukan

sed -e "s/pattern/replacement/g;n"

Tapi itu menggantikan setiap kejadian pertama, bukan yang kedua.

Contoh

File input:

I have a pattern in each line
Also the second line has the pattern
Another pattern here
And -- you guess it -- a pattern

Output yang diinginkan:

I have a pattern in each line
Also the second line has the replacement
Another pattern here
And -- you guess it -- a replacement
Matthieu Riegler
sumber

Jawaban:

6

lihat /programming/5858200/sed-replace-every-nth-occurrence

Solusinya menggunakan awk daripada sed, tetapi "gunakan alat yang tepat untuk pekerjaan itu". Ini mungkin atau mungkin tidak mungkin dapat dilakukan di sed tetapi, bahkan jika itu, itu akan menjadi jauh lebih mudah di alat seperti awk atau perl.

cas
sumber
1
Menggunakan apa yang telah saya pelajari di sana saya pelayan sed -e 'n;s/2004-2009/6e législature/g'yang memecahkan masalah saya.
Matthieu Riegler
1
yang tidak akan mendapatkan setiap detik kejadian , ia akan mencari pola Anda pada setiap detik baris . yaitu lewati baris 1, 3, 5, 7, dll. tentu saja, itu mungkin masih berfungsi untuk dokumen khusus Anda.
cas
Ya saya tahu. itulah yang sebenarnya saya butuhkan.
Matthieu Riegler
14
sed 's/pattern/replacement/2'

Akan mengganti kemunculan kedua pada setiap baris yang memiliki pola.


jika Anda memiliki GNU sed:

sed '1~2N ; s/pattern/replacement/2'

Mulai dari baris satu 1, baris setelah itu akan ditambahkan ke ruang pola Nkemudian sperintah akan menggantikan kemunculan pola kedua. kemudian sedakan memindahkan dua baris ke bawah ~2dan ulangi.

llua
sumber
Saya tidak ingin yang kedua tetapi setiap detik.
Matthieu Riegler
Saya punya satu pola per baris. Itu tidak akan berhasil.
Matthieu Riegler
akan lebih baik untuk mengetahui hal itu sebelumnya. Jadi pola terjadi pada baris satu, dua, tiga dan empat (dll), dan Anda ingin mengganti pola di baris dua, empat, dll?
llua
alternatif yang lebih pendek mungkin code(sed '1 ~ 2s / pola / penggantian /')
jaap
2

Interpretasi sederhana:

Pada baris pertama yang berisi setidaknya satu kemunculan POLA Anda ingin mengabaikannya dan mencetak garis apa adanya. Pada baris kedua yang berisi setidaknya satu kejadian POLA Anda ingin mengganti instance POLA pertama dengan PENGGANTIAN. Pada baris ketiga yang berisi setidaknya satu kemunculan POLA Anda ingin mencetak garis apa adanya. Pada baris keempat yang berisi setidaknya satu kejadian POLA Anda ingin mengganti instance POLA pertama dengan PENGGANTIAN. Dan seterusnya. Garis yang tidak cocok dengan POLA harus dicetak tanpa perubahan.

Ini dapat dengan mudah dilakukan dengan Sed seperti:

sed -e '/PATTERN/ { :inside' -e 'n;s//REPLACEMENT/;t' -e 'b inside' -e '}'

Atau, dengan spasi lebih sedikit dan label lebih pendek:

sed -e '/PATTERN/{:i' -e 'n;s//REPLACEMENT/;t' -e 'b i' -e '}'

EDIT: Saya hanya membaca ulang pertanyaan dan melihat interpretasi yang lebih sulit:

Ganti kemunculan kedua POLA di seluruh dokumen dengan PENGGANTIAN, apakah itu terjadi pada baris yang sama dengan kemunculan pertama atau tidak. Biarkan kejadian pertama dan ketiga tidak berubah. Dll

Saya percaya ini bisa dilakukan dengan Sed juga, meskipun JAUH lebih rumit dan saya percaya itu tergantung pada ekspresi reguler yang akan digunakan. Saya akan mencoba mengerjakan sesuatu dan mempostingnya, tetapi saya akan membiarkan jawaban ini bertahan dengan versi sederhana di atas untuk saat ini.

Wildcard
sumber
ganti test Anda dengan quit dan ambil input seperti, { sed '...'; cat; } <inputhanya untuk satu penggantian
mikeserv
1

Anda sangat dekat, lewati saja baris pertama:

sed '1n;s/pattern/replacement/;n'

Mengapa harus awkmenjadi alat yang lebih baik dalam kasus ini?

Filipos
sumber
0

Satu pola simbol dalam satu baris: sed 's / (a ​​[^ a] *) a / \ 1c / g'

Setiap pola kedua (hanya satu pola yang cocok per baris dapat muncul. Jika dua atau lebih kecocokan per satu baris akan muncul, hanya yang kedua akan diganti)

echo -e "test\nreplace_me\ntest\ntest\nreplace_me\nreplace_me\nreplace_me" | \
sed '/replace_me/{:a;N;/replace_me.*replace_me/!Ta;s/replace_me/replaced/2;}'
buru-buru
sumber