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'

我在教程中读到,要从shell替换环境变量,你需要停止,并“引用”$varname部分,这样它就不会直接被替换,这就是我所做的,并且只有在变量刚刚定义之前才有效。

我如何才能让sed识别$var作为一个环境变量,因为它是在shell中定义的?

354812 次浏览

从你的问题编辑中,我看到了你的问题。假设当前目录是/home/yourname…在这种情况下,你的命令如下:

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

将扩展为

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

这是无效的。如果你想这样做,你需要在$PWD中的每个/前面放一个\字符。

你的两个例子看起来一模一样,这使得问题难以诊断。潜在的问题:

  1. 你可能需要双引号,比如sed 's/xxx/'"$PWD"'/'

  2. $PWD可以包含一个斜杠,在这种情况下,你需要在$PWD中找到一个字符而不是来用作分隔符。

也许是为了同时解决这两个问题

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

除了Norman Ramsey的答案之外,我想补充的是,您可以对整个字符串进行双引号(这可能会使语句更具可读性,更不容易出错)。

因此,如果您想搜索'foo'并将其替换为$BAR的内容,您可以将sed命令括在双引号中。

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

在第一种情况下,$BAR将不能正确展开,而在第二种情况下,$BAR将正确展开。

实际上,最简单的事情(至少在GNU sed中)是为sed替换(s)命令使用不同的分隔符。因此,不要将s/pattern/'$mypath'/扩展为s/pattern//my/path/,这当然会使s命令混淆,而是使用s!pattern!'$mypath'!,它将扩展为s!pattern!/my/path!。我使用了bang (!)字符(或使用任何你喜欢的字符),它避免了通常的,但绝对不是你唯一选择的正斜杠作为分隔符。

你可以使用除"/"之外的其他字符来替换:

sed "s#$1#$2#g" -i FILE

我有类似的问题,我有一个列表,我必须基于模板构建一个SQL脚本(包含@INPUT@作为元素替换):

for i in LIST
do
awk "sub(/\@INPUT\@/,\"${i}\");" template.sql >> output
done
VAR=8675309
echo "abcde:jhdfj$jhbsfiy/.hghi$jh:12345:dgve::" |\
sed 's/:[0-9]*:/:'$VAR':/1'

VAR包含你想要替换的字段

处理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

另一个简单的选择:

由于$PWD通常包含斜杠/,因此在sed语句中使用|而不是/:

sed -e "s|xxx|$PWD|"

一. 坏方法:更改分隔符

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

也许这不是最终答案,

你不知道什么字符将出现在$PWD/:@
如果分隔符字符在$PWD中,它们将中断表达式

好的方法是替换(转义)$PWD中的特殊字符。

二. 好方法:转义分隔符

例如< p >: 尝试将URL替换为$url(内容中有: /)

x.com:80/aa/bb/aa.js

在字符串$tmp

<a href="URL">URL</a>

A.使用/作为分隔符

在var中将/转义为\/(在sed表达式中使用之前)

## step 1: try escape
echo ${url//\//\\/}
x.com:80\/aa\/bb\/aa.js   #escape fine


echo ${url//\//\/}
x.com:80/aa/bb/aa.js      #escape not success


echo "${url//\//\/}"
x.com:80\/aa\/bb\/aa.js   #escape fine, notice `"`




## step 2: do sed
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>

B.使用:作为分隔符(比/更具可读性)

在var中将:转义为\:(在sed表达式中使用之前)

## step 1: try escape
echo ${url//:/\:}
x.com:80/aa/bb/aa.js     #escape not success


echo "${url//:/\:}"
x.com\:80/aa/bb/aa.js    #escape fine, notice `"`




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

如果替换字符串可能包含其他Sed控件字符,那么两步替换(第一个转义替换字符串)可能是你想要的:

PWD='/a\1&b$_' # these are problematic for sed
PWD_ESC=$(printf '%s\n' "$PWD" | sed -e 's/[\/&]/\\&/g')
echo 'xxx' | sed "s/xxx/$PWD_ESC/" # now this works as expected

对我来说,用sed替换文件中环境变量的值的一些文本只适用于配额,如下所示:

sed -i 's/original_value/'"$MY_ENVIRNONMENT_VARIABLE"'/g' myfile.txt

BUT当MY_ENVIRONMENT_VARIABLE的值包含一个URL(即https://andreas.gr)时,上述方法无效。 然后使用不同的分隔符:

sed -i "s|original_value|$MY_ENVIRNONMENT_VARIABLE|g" myfile.txt