Bagaimana Anda meneruskan variabel yang mengandung garis miring sebagai pola sed
?
Misalnya, jika saya memiliki variabel berikut:
var="/Users/Documents/name/file"
Saya ingin meneruskannya sed
sebagai:
sed "s/$var/replace/g" "$file"
Namun saya mendapatkan kesalahan. Bagaimana saya bisa menghindari masalah ini?
$var
Jawaban bash murni: gunakan perluasan parameter untuk menghilangkan garis miring terbalik di setiap garis miring dalam variabel:
sumber
${parameter/pattern/string}
. Jadi, dalam hal ini, parameternya adalahvar
, polanya adalah/\/
, dan stringnya adalah\\/
. Semua contoh pola diganti karena pola dimulai dengan a/
.Cara lain untuk melakukannya, meskipun lebih jelek dari jawaban anubhava, adalah dengan mengosongkan semua garis miring terbalik dengan
var
menggunakansed
perintah lain :kemudian, ini akan berhasil:
sumber
Menggunakan
/
in sed sebagai pembatas akan bertentangan dengan garis miring di variabel saat diganti dan akibatnya Anda akan mendapatkan error. Salah satu cara untuk mengelaknya adalah dengan menggunakan pembatas lain yang unik dari semua karakter yang ada di variabel itu.Anda dapat menggunakan karakter octothorpe yang sesuai dengan acara (atau karakter lain yang bukan
/
untuk kemudahan penggunaan)atau
ini cocok jika variabel tidak mengandung spasi
atau
Lebih bijak untuk menggunakan yang di atas karena kami tertarik untuk mengganti apa pun yang ada di variabel itu hanya dibandingkan dengan mengutip ganda seluruh perintah yang dapat menyebabkan shell Anda menginterpretasikan karakter apa pun yang mungkin dianggap sebagai karakter shell khusus ke shell.
sumber
$var
berisi~
, Anda jelas harus memilih pembatas yang berbeda. Kesalahan "belum diselesaikan" terdengar seperti Anda$var
mengandung baris baru; Anda mungkin bisa memperbaikinya dengan meng-escape setiap baris baru dengan garis miring terbalik dalam nilainya, tetapi menurut saya ini tidak sepenuhnya portabel. Ini pada umumnya tidak terkait dengan masalah garis miring dalam nilai.sed -i "s~blah~$var~g" file
dengan tanda kutip hanya di sekitarsed
skrip yang sebenarnya .Ini adalah pertanyaan lama, tetapi tidak ada jawaban di sini yang membahas operasi selain
s/from/to/
secara mendetail.Bentuk umum
sed
pernyataan adalahdi mana alamat dapat berupa rentang regex atau rentang nomor baris (atau kosong, dalam hal ini tindakan diterapkan ke setiap baris masukan). Jadi contohnya
akan menghapus baris 1 hingga 4 ( alamatnya adalah kisaran nomor baris
1,4
dan tindakannya adalahd
perintah hapus); danakan mengganti kemunculan pertama
foo
denganbar
pada baris mana pun antara kecocokan pertama di regexick
dan akhir file ( alamatnya adalah rentang/ick/,$
dan tindakannya adalahs
perintah penggantis/foo/bar/
).Dalam konteks ini, jika
ick
berasal dari variabel, Anda bisa melakukannya(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
; jadised
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/
:(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:
atau jika Anda menggunakan shell yang berbeda, coba
Untuk kejelasan, jika
$variable
berisi string1/2
maka perintah di atas akan sama dengandalam kasus pertama, dan
di detik.
sumber
Gunakan Perl, di mana variabel adalah warga kelas pertama, tidak hanya memperluas makro:
-p
membaca masukan baris demi baris dan mencetak baris tersebut setelah diproses\Q
mengutip semua karakter meta dalam string berikut (tidak diperlukan untuk nilai yang disajikan di sini, tetapi diperlukan jika nilai berisi[
atau beberapa nilai lain yang khusus untuk ekspresi reguler)sumber