File asli
claudio
antonio
claudio
michele
Saya hanya ingin mengubah kemunculan pertama "claudio" dengan "claudia" jadi hasilnya file
claudia
antonio
claudio
michele
saya telah mencoba
sed -e '1,/claudio/s/claudio/claudia/' nomi
Tetapi lakukan substitusi global. Mengapa?
info sed
: (0,/REGEXP/
: Sejumlah baris 0 dapat digunakan dalam spesifikasi alamat seperti0,/REGEXP/
sehinggased
akan mencoba mencocokkan REGEXP pada baris input pertama juga. Dengan kata lain,0,/REGEXP/
adalah mirip dengan1,/REGEXP/
, kecuali bahwa jika ADDR2 cocok dengan baris pertama input 0, / REGEXP / form akan menganggapnya untuk mengakhiri rentang, sedangkan bentuk 1, / REGEXP / akan cocok dengan awal rentangnya dan karenanya membuat rentang rentang hingga kemunculan kedua dari ekspresi reguler)awk '/claudio/ && !ok { sub(/claudio/,"claudia"); ok=1 } 1' nomi
harus dilakukanJawaban:
Jika Anda menggunakan GNU
sed
, coba:sed
tidak mulai memeriksa regex yang mengakhiri rentang sampai setelah garis yang memulai rentang itu.Dari
man sed
(Halaman manual POSIX, beri penekanan pada tambang):Menggunakan
awk
Kisaran dalam
awk
pekerjaan lebih banyak seperti yang Anda harapkan:Penjelasan:
NR==1,/claudio/
Ini adalah rentang yang dimulai dengan baris 1 dan berakhir dengan kemunculan pertama
claudio
.sub(/claudio/, "claudia")
Sementara kita berada dalam jangkauan, perintah pengganti ini dijalankan.
1
Steno samar cryptic ini untuk mencetak baris.
sumber
sed
.awk '!r && /claudio/ {sub(/claudio/,"claudia"); r=1} 1'
awk !x{x=sub(/claudio/,"claudia")}1
0,/claudio/
Berikut adalah 2 upaya lebih terprogram dengan sed: mereka berdua membaca seluruh file menjadi satu string, maka pencarian hanya akan menggantikan yang pertama.
Dengan komentar:
sumber
Versi baru GNU
sed
mendukung-z
opsi ini.Anda dapat menggunakan opsi ini ketika Anda ingin
sed
bekerja di baris yang berbeda.kembali
sumber
Anda dapat menggunakan
awk
dengan bendera untuk mengetahui apakah penggantian sudah dilakukan. Jika tidak, lanjutkan:sumber
Ini sebenarnya sangat mudah jika Anda hanya mengatur sedikit keterlambatan - tidak perlu menjangkau ekstensi yang tidak dapat diandalkan:
Itu hanya mempertahankan baris pertama ke kedua dan kedua ke ketiga dan lain-lain
Mencetak:
sumber
Dan satu opsi lagi
Keuntungannya adalah menggunakan kutip ganda, sehingga Anda dapat menggunakan variabel di dalamnya, yaitu.
sumber
Ini juga dapat dilakukan tanpa ruang pegang dan tanpa menggabungkan semua garis ke dalam ruang pola:
Penjelasan: Kami mencoba menemukan "claudio" dan jika kami melakukannya, kami beralih ke loop print-load-kecil antara
:x
danbx
. Kalau tidak, kita mencetak dan memulai ulang skrip dengan baris berikutnya.sumber
sumber
Ringkasan
Sintaks GNU:
Atau genap (hanya menggunakan satu kali kata yang akan diganti:
Atau, dalam sintaks POSIX:
bekerja pada sed apa saja, proses hanya sebanyak garis yang diperlukan untuk menemukan yang pertama
claudio
, bekerja bahkan jikaclaudio
berada di baris pertama dan lebih pendek karena hanya menggunakan satu string regex.Detail
Untuk mengubah hanya satu baris, Anda hanya perlu memilih satu baris.
Menggunakan
1,/claudio/
(dari pertanyaan Anda) memilih:claudio
.Untuk memilih setiap baris yang berisi
claudio
, gunakan:Dan untuk memilih hanya yang pertama
claudio
dalam file, gunakan:Kemudian, Anda hanya dapat melakukan substitusi pada baris itu:
Yang hanya akan mengubah kemunculan pertama pertandingan regex di telepon, meskipun mungkin ada lebih dari satu, di baris pertama yang cocok dengan regex.
Tentu saja,
/claudio/
regex dapat disederhanakan untuk:Dan, kemudian, satu-satunya hal yang hilang adalah mencetak semua baris lain yang tidak dimodifikasi:
sumber