変数を使用してシェルスクリプトの文字列を置き換える


93

シェルスクリプト内の文字列を置き換えるために以下のコードを使用しています。

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

しかし$replace、その変数の値の代わりに置き換えられています。

誰かが何が悪かったのか教えてもらえますか?


スラッシュを含む値の処理に関する一般的な関連質問については、stackoverflow.com
questions / 5864146 / use

回答:


146

を解釈$replaceする場合は、変数の置換を妨げるため、一重引用符を使用しないでください。

試してください:

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

。あなたがいる場合は、引用符を入れたいと想定していない引用符をしたい、使用:

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

筆記録:

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

エスケープしないと混乱を招くため、(たとえば)${replace}重要な文字が含まれていないことを確認してください。しかし、あなたが言うように、ある数値を別の数値に置き換えるのであれば、それは問題にはなりません。sed/


引用符を入れたくない。1つの番号を他の番号に置き換えたい
Vijay

1
paxdiablo:setも必要ありません(とにかくそれをどのように使用する予定でしたか?)。ただreplace=987654321
Roman Cheplyaka

私は通常、常にexport変数が子供用に設定されていることを確認するために使用しますが、あなたが言うように、それを簡単に回避することもできます。ただし、exportここでの使用の有無は関係なく(スタイルの問題)、実際の回答(sedコマンド内での変数の使用方法)には影響しません。
paxdiablo 2014年

このソリューションは-iオプションで動作していないようです。なぜでしょうか?またはそれを機能させる方法は?
ガブリエル

1
また、一重引用符から二重引用符に切り替えるには、スクリプト内で、$または二重引用符で囲まれた文字列のシェルの置換メカニズムから保護するために、バックスラッシュでエスケープする必要があることも指摘します。`sed
tripleee 2016年

73

シェル(bash / ksh)を使用できます。

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

3
これはbash固有である(およびkshか?)おそらくほとんどの人にとって重要ではありませんが、私たちの一部は依然として古代のUNIXenに取り組むことを余儀なくされています:-)
paxdiablo

6
注意してください、これは/bin/sh多くの最近のLinuxにあるダッシュでも失敗します。
phihag 2015年

26

質問に固有ではありませんが、以前の回答から明確にするために同じ種類の機能を拡張する必要がある人のために:

# 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

一重引用符は非常に強力です。いったん中に入ると、去るまで、変数置換を呼び出すためにできることは何もありません。代わりに二重引用符を使用してください:

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


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

単一引用符は引き続き使用できますが、変数を適切な場所に展開する場合は、それらを「開く」必要があります。そうでない場合、文字列は「文字通り」に解釈されます(@paxdiabloが正しく述べられているように、彼の答えも正しいです)


これには、$replace引用符の外で使用すると、シェルが値に対して空白のトークン化とワイルドカード拡張を実行するという問題があります。これは単純な値で機能するように見えますが、重要な文字列で劇的に爆発する可能性があります。これを本番コードで使用しないでください。
tripleee 2016年

2

シェルに変数を展開させるには、次のような二重引用符を使用する必要があります

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

これは$replace、特殊sed文字(#\)が含まれていると壊れます。しかし、あなたは$replaceそれらを引用するために前処理することができます:

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

0

これと同様の要件がありましたが、私の置換変数にはアンパサンドが含まれていました。このようにアンパサンドをエスケープすると、私の問題が解決しました。

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

-1

代わりにこれを使用してください

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

これは私にとってはうまくいきます


-2

二重引用符を使用することをお勧めします。単一のクプテスは、内部を変更できない場合や変数の置換を呼び出すことができない場合に使用したのと同じように非常に強力です。

二重引用符を使用してください。

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

6
これはDaveの回答とは異なりますか?
devnull 2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.