Ganti string dalam skrip shell menggunakan variabel


Jawaban:


147

Jika Anda ingin menafsirkan $replace, Anda tidak boleh menggunakan tanda kutip tunggal karena mereka mencegah substitusi variabel.

Mencoba:

echo $LINE | sed -e "s/12345678/\"${replace}\"/g"

dengan asumsi Anda ingin kutipan dimasukkan. Jika Anda tidak menginginkan kutipan, gunakan:

echo $LINE | sed -e "s/12345678/${replace}/g"

Salinan:

pax> export replace=987654321
pax> echo X123456789X | sed "s/123456789/${replace}/"
X987654321X
pax> _

Berhati-hatilah untuk memastikan bahwa ${replace}tidak ada karakter yang penting sed(seperti /misalnya) karena akan menyebabkan kebingungan kecuali lolos. Tetapi jika, seperti yang Anda katakan, Anda mengganti satu nomor dengan yang lain, itu seharusnya tidak menjadi masalah.


saya tidak ingin kutipan dimasukkan. saya ingin satu nomor diganti dengan yang lain
Vijay

1
paxdiablo: setjuga tidak perlu (dan bagaimana Anda akan menggunakannya?). Cuma replace=987654321.
Roman Cheplyaka

Saya biasanya selalu menggunakan exportuntuk memastikan bahwa variabel ditetapkan untuk anak-anak tetapi, seperti yang Anda katakan, Anda dapat dengan mudah menghindarinya. Namun, penggunaan atau tidak dari exporttidak relevan di sini (masalah gaya) dan tidak berpengaruh pada jawaban sebenarnya, yaitu bagaimana menggunakan variabel dalam sedperintah.
paxdiablo

Solusi ini tampaknya tidak berfungsi dengan -iopsi tersebut. Tahukah kamu mengapa? atau bagaimana cara membuatnya bekerja?
Gabriel

1
Mungkin juga menunjukkan bahwa beralih dari tanda kutip tunggal ke ganda memerlukan salah satu $atau `dalam sedskrip untuk di-escape dengan garis miring terbalik, untuk melindunginya dari mekanisme substitusi shell untuk string yang dikutip ganda.
tripleee

74

Anda bisa menggunakan shell (bash / ksh).

$ var="12345678abc"
$ replace="test"
$ echo ${var//12345678/$replace}
testabc

3
Mungkin ingin menyebutkan itu khusus bash (dan ksh?). Mungkin tidak diimpor ke kebanyakan orang tetapi beberapa dari kita masih dipaksa untuk mengerjakan UNIXen kuno :-)
paxdiablo

6
Hati-hati, ini juga gagal pada dasbor, yang ada /bin/shdi banyak Linux modern.
phihag

28

Tidak spesifik untuk pertanyaan tersebut, tetapi untuk orang-orang yang membutuhkan jenis fungsionalitas yang sama yang diperluas untuk kejelasan dari jawaban sebelumnya:

# create some variables
str="someFileName.foo"
find=".foo"
replace=".bar"
# notice the the str isn't prefixed with $
#    this is just how this feature works :/
result=${str//$find/$replace}
echo $result    
# result is: someFileName.bar

str="someFileName.sally"
find=".foo"
replace=".bar"
result=${str//$find/$replace}
echo $result    
# result is: someFileName.sally because ".foo" was not found


8

Tanda kutip tunggal sangat kuat. Begitu masuk, tidak ada yang dapat Anda lakukan untuk memanggil substitusi variabel, sampai Anda pergi. Gunakan tanda kutip ganda sebagai gantinya:

echo $LINE | sed -e "s/12345678/$replace/g"

4
echo $LINE | sed -e 's/12345678/'$replace'/g'

Anda masih dapat menggunakan tanda kutip tunggal, tetapi Anda harus "membukanya" jika ingin variabel diperluas di tempat yang tepat. jika tidak, string akan diambil "secara harfiah" (seperti @paxdiablo dinyatakan dengan benar, jawabannya juga benar)


Ini memiliki masalah bahwa menggunakan di $replaceluar tanda kutip apa pun akan menyebabkan shell melakukan tokenisasi spasi putih dan perluasan karakter pengganti pada nilainya. Ini akan tampak bekerja dengan nilai-nilai sederhana, tetapi bisa meledak secara dramatis pada string nontrivial. Jangan gunakan ini dalam kode produksi.
tripleee

2

Untuk membiarkan shell Anda memperluas variabel, Anda perlu menggunakan tanda kutip ganda seperti

sed -i "s#12345678#$replace#g" file.txt

Ini akan rusak jika $replaceberisi sedkarakter khusus ( #, \). Tetapi Anda dapat melakukan praproses $replaceuntuk mengutipnya:

replace_quoted=$(printf '%s' "$replace" | sed 's/[#\]/\\\0/g')
sed -i "s#12345678#$replace_quoted#g" file.txt

0

Saya memiliki persyaratan yang mirip dengan ini tetapi var pengganti saya mengandung ampersand. Melarikan diri dari ampers dan seperti ini memecahkan masalah saya:

replace="salt & pepper"
echo "pass the salt" | sed "s/salt/${replace/&/\&}/g"

-1

Gunakan ini sebagai gantinya

echo $LINE | sed -e 's/12345678/$replace/g'

ini berfungsi untuk saya, cukup hapus tanda kutip


-2

Saya lebih suka menggunakan tanda kutip ganda, karena quptes tunggal sangat kuat karena kami menggunakannya jika tidak dapat mengubah apa pun di dalamnya atau dapat memanggil penggantian variabel.

jadi gunakan tanda kutip ganda.

echo $LINE | sed -e "s/12345678/$replace/g"

6
Apakah ini berbeda dengan jawaban Dave ?
devnull
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.