Kabuk betiğindeki bir dizeyi bir değişken kullanarak değiştirin


94

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 $replacedeğişkenin değeri yerine ile değiştiriliyor .

Neyin yanlış gittiğini bilen var mı?


Yanıtlar:


147

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/


Alıntıların eklenmesini istemiyorum. bir sayının diğeriyle değiştirilmesini istiyorum
Vijay

1
paxdiablo: setayrıca gerekli de değil (ve bunu nasıl kullanacaktın zaten?). Sadece replace=987654321.
Roman Cheplyaka

Genelde exportdeğ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ı exportalakasızdır (bir stil sorunu) ve bir sedkomut içinde değişkenlerin nasıl kullanılacağı olan gerçek cevap üzerinde hiçbir etkisi yoktur .
paxdiablo

Bu çözüm -iseçenekle işe yaramıyor gibi görünüyor . Neden olduğunu biliyor musun? ya da nasıl çalıştırılır?
Gabriel

1
Belki de tek tırnaktan çift tırnağa geçişin , kabuğun çift tırnaklı dizeler için ikame mekanizmasından korumak için komut dosyasında herhangi bir $veya bir ters eğik çizgiyle kaçılmasını gerektirdiğini de belirtebilirsiniz. `sed
üçlü

74

kabuğu (bash / ksh) kullanabilirsiniz.

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

3
Bunun bash'a özgü (ve ksh?) Olduğunu belirtmek isterim. Muhtemelen çoğu insan için ithalat ama bazılarımız hala :-) antik UNIXen üzerinde çalışmaya zorlanmaktadır değil
paxdiablo

6
Dikkat edin, bu aynı zamanda /bin/shbirçok modern Linux'ta olduğu gibi kısa sürede başarısız olur .
phihag

28

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


8

Tek tırnak çok güçlüdür. İçeri girdikten sonra, ayrılıncaya kadar değişken ikamesini çağırmak için yapabileceğiniz hiçbir şey yoktur. Bunun yerine çift tırnak kullanın:

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

4
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)


Bu, $replaceherhangi 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.
üçlü

2

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 sedkarakterler ( #, \) içeriyorsa bozulur . Ancak $replacebunlardan 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

0

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"

-1

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


-2

Ç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"

6
Bu Dave'in cevabından farklı mı ?
devnull
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.