English 中文(简体)
sed 中的环境变量替换
原标题:
  • 时间:2009-02-25 06:10:31
  •  标签:

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

#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中定义的方式操作?

最佳回答

您的两个示例看起来完全相同,这使得问题难以诊断。 可能出现的问题:

  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 将展开正确。

另一个简单的选择:

由于$PWD通常包含斜杠/,因此请在sed语句中使用|代替/

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

您可以使用替代符号“/”以外的其他字符:

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

一. bad way: change delimiter

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

也许那并非最终答案。

you can not known what character will occur in $PWD, / : 或者 @.
if delimiter char in $PWD, they will break the expression

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

二. good way: escape delimiter

for example: try to replace URL as $url (has : / in content)

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

在字符串 $tmp 中

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

A. use / as delimiter

在使用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. use : as delimiter (more readable than /)

在使用sed表达式之前,在var中将:转义为。 在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>

通过您的问题编辑,我了解到您的困惑。假设当前目录为/home/yourname...在这种情况下,您下面的命令是:

sed  s/xxx/ $PWD / 

将被扩展到

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

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

实际上,在GNU sed中,最简单的方法是为sed替换(s)命令使用不同的分隔符。因此,不要将s/pattern/ $mypath /扩展为s/pattern//my/path/,这当然会使s命令混淆,而是使用s!pattern! $mypath !,这将被扩展为s!pattern!/my/path!。我使用了惊叹号(!)字符(或者使用任何您喜欢的字符),避免通常但并非唯一选择的"/"斜杠作为分隔符。

处理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
VAR=8675309
echo "abcde:jhdfj$jhbsfiy/.hghi$jh:12345:dgve::" |
sed  s/:[0-9]*:/: $VAR :/1  

其中VAR包含您要用于替换该字段的内容

如果你的替换字符串可能包含其他sed控制字符,那么进行两步替换(首先转义替换字符串)可能是你想要的:

PWD= /a1&b$_  # these are problematic for sed
PWD_ESC=$(printf  %s
  "$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

对我来说,使用sed在文件中根据环境变量的值替换一些文本只能使用引号,如下所示:

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

BUT when the value of MY_ENVIRONMENT_VARIABLE contains a URL (ie https://andreas.gr) then the above was not working. THEN use different delimiter:

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




相关问题
热门标签