如果我从脚本中运行这些命令:

#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中定义的?


当前回答

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

您可能需要双引号,例如sed 's/xxx/'"$PWD"'/' $PWD可能包含斜杠,在这种情况下,需要找到$PWD中不包含的字符用作分隔符。

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

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

其他回答

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

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

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

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

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

如果替换字符串可能包含其他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

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

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

实际上,最简单的方法(至少在GNU sed中)是为sed substitution (s)命令使用不同的分隔符。因此,与其将s/pattern/'$mypath'/扩展为s/pattern//my/path/,这当然会混淆s命令,不如使用s!pattern!'$mypath'!,扩展为s!pattern!/my/path!。我使用了bang(!)字符(或其他您喜欢的字符),它避免了通常的,但绝不是您唯一选择的正斜杠作为分隔符。