web-dev-qa-db-ja.com

sedでの環境変数の置換

これらのコマンドをスクリプトから実行する場合:

#my.sh
PWD=bla
sed 's/xxx/'$PWD'/'
...
$ ./my.sh
xxx
bla

それは結構です。

しかし、私が実行した場合:

#my.sh
sed 's/xxx/'$PWD'/'
...
$ ./my.sh
$ sed: -e expression #1, char 8: Unknown option to `s' 

私はチュートリアルで、停止する必要があるシェルの環境変数を置き換えるために$varname部分を「引用符で囲む」ことを読んで、直接置き換えられないようにします。これは私がやったことであり、変数が直前に定義されている場合にのみ機能します。

$varをシェルで定義されている環境変数として認識するようにするにはどうすればよいですか?

156
Roman M

2つの例は同じように見えるため、問題の診断が難しくなります。潜在的な問題:

  1. sed 's/xxx/'"$PWD"'/'のように、二重引用符が必要な場合があります

  2. $PWDにはスラッシュが含まれる場合があります。その場合は、区切り文字として使用するために$PWDに含まれる文字notを見つける必要があります。

両方の問題を一度にネイルするために、おそらく

sed 's@xxx@'"$PWD"'@'
248
Norman Ramsey

Norman Ramseyの答えに加えて、文字列全体を二重引用符で囲むことができることを付け加えます(これにより、ステートメントが読みやすくなり、エラーが発生しにくくなります)。

したがって、「foo」を検索して$ BARのコンテンツに置き換える場合は、sedコマンドを二重引用符で囲むことができます。

sed 's/foo/$BAR/g'
sed "s/foo/$BAR/g"

最初の$ BARは正しく展開されませんが、2番目の$ BARは正しく展開されます。

88
Jeach

置換には「/」以外の文字を使用できます。

sed "s#$1#$2#g" -i FILE
54
Paulo Fidalgo

別の簡単な代替手段:

$PWDは通常スラッシュ/を含むため、sedステートメントには|の代わりに/を使用します。

sed -e "s|xxx|$PWD|"
40
Thales Ceolin

質問を編集すると、問題がわかります。現在のディレクトリが/home/yournameであるとしましょう...この場合、以下のコマンド:

sed 's/xxx/'$PWD'/'

に展開されます

sed `s/xxx//home/yourname//

無効です。これを行うには、$ PWDの各\の前に/文字を配置する必要があります。

13
Eddie
VAR=8675309
echo "abcde:jhdfj$jhbsfiy/.hghi$jh:12345:dgve::" |\
sed 's/:[0-9]*:/:'$VAR':/1' 

vARには、フィールドを置き換えるものが含まれます

3
PsychoData

悪い方法:区切り文字を変更する

sed 's/xxx/'"$PWD"'/'
sed 's:xxx:'"$PWD"':'
sed 's@xxx@'"$PWD"'@'

多分それらは最終的な答えではない、

$PWD/: OR @でどの文字が発生するかを知ることはできません。

良い方法は、$PWDの特殊文字を置き換えることです。

良い方法:区切り文字をエスケープする

例えば:

区切り文字として/を使用します

echo ${url//\//\\/}
x.com:80\/aa\/bb\/aa.js

echo ${url//\//\/}
x.com:80/aa/bb/aa.js

echo "${url//\//\/}"
x.com:80\/aa\/bb\/aa.js

echo $tmp | sed "s/URL/${url//\//\\/}/"
<a href="x.com:80/aa/bb/aa.js">URL</a>

echo $tmp | sed "s/URL/${url//\//\/}/"
<a href="x.com:80/aa/bb/aa.js">URL</a>

OR

区切り文字として:を使用します(/より読みやすい)

echo ${url//:/\:}
x.com:80/aa/bb/aa.js

echo "${url//:/\:}"
x.com\:80/aa/bb/aa.js

echo $tmp | sed "s:URL:${url//:/\:}:g"
<a href="x.com:80/aa/bb/aa.js">x.com:80/aa/bb/aa.js</a>
3
yurenchen

実際、(少なくともgnu sedで)最も簡単なことは、sed substitution(s)コマンドに異なるセパレーターを使用することです。したがって、s/pattern/'$ mypath' /をs/pattern // my/path /に展開する代わりに、もちろんsコマンドを混乱させる代わりに、s!pattern! '$ mypath'を使用してください!これはs!pattern!/ my/path!に展開されます。区切り記号として通常の、しかし意味のない、あなただけの選択肢のスラッシュを回避するバング(!)文字を使用しました(または好きなものを使用します)。

2
adeger

同様の問題があり、リストがあり、テンプレート(置換する要素として@INPUT@を含む)に基づいてSQLスクリプトを作成する必要があります。

for i in LIST 
do
    awk "sub(/\@INPUT\@/,\"${i}\");" template.sql >> output
done
1
aniskop

sed内の変数の処理

[root@gislab00207 ldom]# echo domainname: None > /tmp/1.txt

[root@gislab00207 ldom]# cat /tmp/1.txt

domainname: None

[root@gislab00207 ldom]# echo ${DOMAIN_NAME}

dcsw-79-98vm.us.Oracle.com

[root@gislab00207 ldom]# cat /tmp/1.txt | sed -e 's/domainname: None/domainname: ${DOMAIN_NAME}/g'

 --- Below is the result -- very funny.

domainname: ${DOMAIN_NAME}

 --- You need to single quote your variable like this ... 

[root@gislab00207 ldom]# cat /tmp/1.txt | sed -e 's/domainname: None/domainname: '${DOMAIN_NAME}'/g'


--- The right result is below 

domainname: dcsw-79-98vm.us.Oracle.com