Dalam skrip bash saya, saya memiliki string eksternal (diterima dari pengguna), yang harus saya gunakan dalam pola sed.
REPLACE="<funny characters here>"
sed "s/KEYWORD/$REPLACE/g"
Bagaimana saya bisa lepas dari $REPLACE
string sehingga akan diterima dengan aman sed
sebagai pengganti literal?
CATATAN: The KEYWORD
adalah substring bodoh dengan tidak ada pertandingan dll Hal ini tidak disediakan oleh pengguna.
outputvar="${inputvar//"$txt2replace"/"$txt2replacewith"}".
Jawaban:
Peringatan : Ini tidak mempertimbangkan baris baru. Untuk jawaban yang lebih mendalam, lihat pertanyaan SO ini . (Terima kasih, Ed Morton & Niklas Peter)
Perhatikan bahwa melarikan diri dari segala sesuatu adalah ide yang buruk. Sed membutuhkan banyak karakter untuk melarikan diri untuk mendapatkan makna khusus mereka. Misalnya, jika Anda melepaskan satu digit dalam string pengganti, itu akan berubah menjadi referensi-ulang.
Seperti yang dikatakan Ben Blank, hanya ada tiga karakter yang perlu diloloskan dalam string pengganti (melarikan diri, meneruskan garis miring untuk akhir pernyataan dan & untuk mengganti semua):
Jika Anda perlu keluar dari
KEYWORD
string, berikut ini yang Anda butuhkan:Dan bisa digunakan oleh:
Ingat, jika Anda menggunakan karakter selain
/
sebagai pembatas, Anda perlu mengganti garis miring pada ekspresi di atas dengan karakter yang Anda gunakan. Lihat komentar PeterJCLaw untuk penjelasan.Diedit: Karena beberapa kasus sudut yang sebelumnya tidak diperhitungkan, perintah di atas telah berubah beberapa kali. Periksa riwayat edit untuk detailnya.
sumber
KEYWORD
, di sed GNU , berikut adalah 2 karakter lagi^
,$
tidak disebutkan di atas:s/[]\/$*.^|[]/\\&/g
A='foo"bar' echo $A | sed s/$A/baz/
di bash. Kutipan ganda diperlakukan seperti 'foo' dan 'bar' di sekitarnyaPerintah sed memungkinkan Anda untuk menggunakan karakter lain alih-alih
/
sebagai pemisah:Kutipan ganda tidak masalah.
sumber
.
yang sebaliknya memiliki arti khusus. Saya mengedit jawaban Anda.sed '/CLIENTSCRIPT="foo"/a CLIENTSCRIPT2="hello"' file
dengansed '|CLIENTSCRIPT="foo"|a CLIENTSCRIPT2="hello"' file
dan itu tidak melakukan hal yang sama.s
Perintah (seperti dalam pengganti) sed memungkinkan Anda untuk menggunakan karakter lain alih-alih / sebagai pemisah. Juga, ini akan menjadi jawaban untuk bagaimana menggunakan sed pada URL dengan karakter garis miring. Itu tidak menjawab pertanyaan OP bagaimana melepaskan string yang dimasukkan oleh pengguna, yang bisa berisi /, \, tetapi juga # jika Anda memutuskan untuk menggunakannya. Dan selain itu, URI dapat berisi # terlaluHanya tiga karakter literal yang diperlakukan secara khusus dalam klausa penggantian adalah
/
(untuk menutup klausa),\
(untuk menghindari karakter, backreference, & c.), Dan&
(untuk memasukkan kecocokan dalam penggantian). Karena itu, yang perlu Anda lakukan adalah melarikan diri dari ketiga karakter:Contoh:
sumber
Berdasarkan ekspresi reguler Pianosaurus, saya membuat fungsi bash yang lolos dari kata kunci dan penggantian.
Begini cara Anda menggunakannya:
sumber
man echo
), menyebabkan pipa untuk berperilaku tak terduga ketika argumen Anda$1
dimulai dengan tanda hubung. Sebagai gantinya, Anda dapat memulai pipa Anda denganprintf '%s\n' "$1"
.Agak terlambat untuk merespons ... tetapi ADA cara yang lebih sederhana untuk melakukan ini. Ubah saja pembatas (yaitu, karakter yang memisahkan bidang). Jadi, alih-alih
s/foo/bar/
Anda menuliss|bar|foo
.Dan, inilah cara mudah untuk melakukan ini:
Output yang dihasilkan tidak memiliki klausa DEFINER yang jahat itu.
sumber
&
dan `` masih harus diloloskan, seperti juga pembatas, yang dipilih.$
dalam string yang akan diubah, dan mempertahankan makna$
dalam string pengganti. katakanlah saya ingin mengubah$XXX
ke nilai variabel$YYY
,sed -i "s|\$XXX|$YYY|g" file
berfungsi dengan baik.Ternyata Anda mengajukan pertanyaan yang salah. Saya juga mengajukan pertanyaan yang salah. Alasannya salah adalah awal dari kalimat pertama: "Dalam skrip bash saya ...".
Saya memiliki pertanyaan yang sama & membuat kesalahan yang sama. Jika Anda menggunakan bash, Anda tidak perlu menggunakan sed untuk melakukan penggantian string (dan jauh lebih bersih untuk menggunakan fitur ganti yang dibangun menjadi bash).
Alih-alih sesuatu seperti, misalnya:
Anda dapat menggunakan fitur bash secara eksklusif:
sumber
$A
dan$B
tidak dikutip, tetapi sebenarnya tidak. Kutipan di dalam${}
tidak cocok dengan kutipan di luarnya.var='has space'
) -OUTPUT=${INPUT//"$A"/"$B"}
aman.Gunakan awk - lebih bersih:
sumber
awk
adalah tidak ada yang mirip dengan itused -i
, yang sangat berguna 99% dari waktu.Ini adalah contoh AWK yang saya gunakan beberapa waktu lalu. Ini adalah AWK yang mencetak AWKS baru. AWK dan SED yang serupa mungkin merupakan templat yang baik.
Kelihatannya berlebihan, tetapi entah bagaimana kombinasi dari kutipan berfungsi untuk menjaga 'dicetak sebagai literal. Maka jika saya ingat dengan benar, vaiables hanya dikelilingi dengan tanda kutip seperti ini: "$ 1". Cobalah, beri tahu saya cara kerjanya dengan SED.
sumber
Saya memiliki peningkatan atas fungsi sedeasy, yang AKAN putus dengan karakter khusus seperti tab.
Jadi, apa bedanya?
$1
dan$2
dibungkus dengan tanda kutip untuk menghindari ekspansi shell dan mempertahankan tab atau spasi ganda.Perpipaan tambahan
| sed -e 's:\t:\\t:g'
(saya suka:
sebagai token) yang mengubah tab di\t
.sumber
Ini adalah kode pelarian yang saya temukan:
sumber
jangan lupa semua kesenangan yang terjadi dengan batasan shell di sekitar "dan '
jadi (dalam ksh)
sumber
Jika Anda hanya ingin mengganti nilai Variabel dalam perintah sed maka hapus saja Contoh:
sumber
Jika Anda menggunakan kata sandi acak untuk
sed
mengganti untuk mengganti pola, maka Anda memilih untuk berhati-hati tentang set karakter mana dalam string acak. Jika Anda memilih kata sandi yang dibuat dengan menyandikan nilai sebagai base64, maka hanya ada karakter yang dimungkinkan pada base64 dan juga karakter khusus dalamsed
pola ganti. Karakter itu adalah "/", dan mudah dihapus dari kata sandi yang Anda hasilkan:sumber
Cara yang lebih mudah untuk melakukan ini adalah dengan membangun string sebelum tangan dan menggunakannya sebagai parameter untuk
sed
sumber
REPLACE=/
memberikansed: -e expression #1, char 12: unknown option to `s'