Bir kabuk komut dosyası içindeki bir dizeyi değiştirmek için aşağıdaki kodu kullanıyorum.
echo $LINE | sed -e 's/12345678/"$replace"/g'
ancak bu $replace
değişkenin değeri yerine ile değiştiriliyor .
Neyin yanlış gittiğini bilen var mı?
Yanıtlar:
Yorumlamak istiyorsanız $replace
, değişken ikamesini engelledikleri için tek tırnak kullanmamalısınız.
Deneyin:
echo $LINE | sed -e "s/12345678/\"${replace}\"/g"
Eğer tırnak koymak istiyorum varsayarak Eğer varsa. yok , kullanımı tırnak istiyorum:
echo $LINE | sed -e "s/12345678/${replace}/g"
Transcript:
pax> export replace=987654321
pax> echo X123456789X | sed "s/123456789/${replace}/"
X987654321X
pax> _
Kaçılmadığı sürece kafa karışıklığına neden olacağından ( örneğin gibi ) ${replace}
herhangi bir önemli karakter içermediğinden emin olun . Ancak, dediğiniz gibi, bir sayıyı diğeriyle değiştiriyorsanız, bu bir sorun olmamalı.sed
/
set
ayrıca gerekli de değil (ve bunu nasıl kullanacaktın zaten?). Sadece replace=987654321
.
export
değişkenlerin çocuklar için ayarlandığından emin olmak için kullanırım , ancak sizin de dediğiniz gibi, bundan kolayca kaçınabilirsiniz. Bununla birlikte, burada kullanımı ya da olmaması export
alakasızdır (bir stil sorunu) ve bir sed
komut içinde değişkenlerin nasıl kullanılacağı olan gerçek cevap üzerinde hiçbir etkisi yoktur .
-i
seçenekle işe yaramıyor gibi görünüyor . Neden olduğunu biliyor musun? ya da nasıl çalıştırılır?
$
veya bir ters eğik çizgiyle kaçılmasını gerektirdiğini de belirtebilirsiniz. `
sed
kabuğu (bash / ksh) kullanabilirsiniz.
$ var="12345678abc"
$ replace="test"
$ echo ${var//12345678/$replace}
testabc
/bin/sh
birçok modern Linux'ta olduğu gibi kısa sürede başarısız olur .
Soruya özel değil, aynı türden işlevselliğe ihtiyaç duyan kişiler için, önceki cevaplardan daha net anlaşılması için genişletildi:
# 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
Found zarif bir çözüm .
echo ${LINE//12345678/$replace}
echo $LINE | sed -e 's/12345678/'$replace'/g'
Yine de tek tırnak işaretleri kullanabilirsiniz, ancak değişkenin doğru yerde genişletilmesini istediğinizde onları "açmanız" gerekir. aksi takdirde dize "kelimenin tam anlamıyla" alınır (@paxdiablo'nun doğru bir şekilde belirtildiği gibi, yanıtı da doğrudur)
$replace
herhangi bir tırnak işaretinin dışını kullanmanın , kabuğun değer üzerinde boşluk belirteci haline getirme ve joker karakter genişletme gerçekleştirmesine neden olması sorununa sahiptir . Bu, basit değerlerle işe yarıyor gibi görünecek, ancak önemsiz dizelerde çarpıcı bir şekilde patlayabilir. Bunu üretim kodunda kullanmayın.
Kabuğunuzun değişkeni genişletmesine izin vermek için, aşağıdaki gibi çift tırnak işaretleri kullanmanız gerekir:
sed -i "s#12345678#$replace#g" file.txt
Bu, $replace
özel sed
karakterler ( #
, \
) içeriyorsa bozulur . Ancak $replace
bunlardan alıntı yapmak için ön işlem yapabilirsiniz :
replace_quoted=$(printf '%s' "$replace" | sed 's/[#\]/\\\0/g')
sed -i "s#12345678#$replace_quoted#g" file.txt
Buna benzer bir gereksinimim vardı, ancak değiştirilen değişkenim bir ve işareti içeriyordu. Ve işaretinden bu şekilde kaçmak sorunumu çözdü:
replace="salt & pepper"
echo "pass the salt" | sed "s/salt/${replace/&/\&}/g"
Bunun yerine bunu kullan
echo $LINE | sed -e 's/12345678/$replace/g'
bu benim için çalışıyor sadece alıntıları kaldırın
Çift tırnak kullanmayı tercih ederim, çünkü tek qupte, içinde hiçbir şeyi değiştiremiyorsak veya değişken ikamesini çağırabiliyorsa, onları kullandığımız için çok güçlüdür.
bu nedenle çift tırnak işareti kullanın.
echo $LINE | sed -e "s/12345678/$replace/g"