Ini adalah pertanyaan lama, tetapi tidak ada jawaban di sini yang membahas operasi selain s/from/to/
secara mendetail.
Bentuk umum sed
pernyataan adalah
*address* *action*
di mana alamat dapat berupa rentang regex atau rentang nomor baris (atau kosong, dalam hal ini tindakan diterapkan ke setiap baris masukan). Jadi contohnya
sed '1,4d' file
akan menghapus baris 1 hingga 4 ( alamatnya adalah kisaran nomor baris 1,4
dan tindakannya adalah d
perintah hapus); dan
sed '/ick/,$s/foo/bar/' file
akan mengganti kemunculan pertama foo
dengan bar
pada baris mana pun antara kecocokan pertama di regex ick
dan akhir file ( alamatnya adalah rentang /ick/,$
dan tindakannya adalah s
perintah pengganti s/foo/bar/
).
Dalam konteks ini, jika ick
berasal dari variabel, Anda bisa melakukannya
sed "/$variable/,\$s/foo/bar/"
(perhatikan penggunaan tanda kutip ganda, bukan tanda kutip tunggal, sehingga shell dapat menginterpolasi variabel, dan kebutuhan untuk mengutip tanda dolar literal di dalam tanda kutip ganda) tetapi jika variabel tersebut berisi garis miring, Anda akan mendapatkan kesalahan sintaks. (Shell memperluas variabel, lalu meneruskan string yang dihasilkan ke sed
; jadi sed
hanya melihat teks literal - ia tidak memiliki konsep variabel shell.)
Obatnya adalah dengan menggunakan pembatas yang berbeda (di mana jelas Anda harus dapat menggunakan karakter yang tidak dapat terjadi dalam nilai variabel), tetapi tidak seperti dalam s%foo%bar%
kasus ini, Anda juga memerlukan garis miring terbalik sebelum pembatas jika Anda ingin menggunakan karakter yang berbeda. pembatas dari default /
:
sed "\\%$variable%,\$s/foo/bar/" file
(di dalam tanda kutip tunggal, satu garis miring terbalik sudah cukup); atau Anda dapat melepaskan diri dari setiap garis miring pada nilai secara terpisah. Sintaks khusus ini hanya Bash:
sed "/${variable//\//\\/}/,\$s/foo/bar/" file
atau jika Anda menggunakan shell yang berbeda, coba
escaped=$(echo "$variable" | sed 's%/%\\/%g')
sed "s/$escaped/,\$s/foo/bar/" file
Untuk kejelasan, jika $variable
berisi string 1/2
maka perintah di atas akan sama dengan
sed '\%1/2%,$s/foo/bar/' file
dalam kasus pertama, dan
sed '/1\/2/,$s/foo/bar/' file
di detik.