sed中的环境变量替换

Rom*_*n M 170 unix linux shell sed

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

#my.sh
PWD=bla
sed 's/xxx/'$PWD'/'
...
$ ./my.sh
xxx
bla
Run Code Online (Sandbox Code Playgroud)

没事.

但是,如果我跑:

#my.sh
sed 's/xxx/'$PWD'/'
...
$ ./my.sh
$ sed: -e expression #1, char 8: Unknown option to `s' 
Run Code Online (Sandbox Code Playgroud)

我在教程中读到要替换你需要停止的shell中的环境变量,并且"引用"该$varname部分以便它不直接替换,这就是我所做的,并且只有在之前定义变量时才有效.

我怎样才能将sed识别$var为在shell中定义的环境变量?

Nor*_*sey 270

您的两个示例看起来完全相同,这使问题难以诊断.潜在问题:

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

  2. $PWD可能包含斜杠,在这种情况下,您需要找到一个包含的字符$PWD用作分隔符.

或许可以立刻解决这两个问题

sed 's@xxx@'"$PWD"'@'
Run Code Online (Sandbox Code Playgroud)

  • 你可以有几个候选人,比如@#%!并检查案例表达式以查找$ PWD是否具有它们.例如,*@*的案例"$ PWD";;*)delim ="@";; ESAC; 重复直到$ delim不为空. (5认同)

Jea*_*ach 97

除了Norman Ramsey的回答之外,我还想补充一点,你可以对整个字符串进行双引号(这可能使语句更具可读性,更不容易出错).

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

sed 's/foo/$BAR/g'
sed "s/foo/$BAR/g"
Run Code Online (Sandbox Code Playgroud)

在第一个,$ BAR将无法正确扩展,而在第二个$ BAR将正确扩展.

  • 这比弄乱双引号,单引号等更干净. (4认同)
  • 这很整洁,但是当你想做一些更复杂的替换时它就不能工作了,例如``2,$ s/^/$ foo /"```$ s`也被解释为变量而它不应该. (2认同)

Pau*_*lgo 56

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

sed "s#$1#$2#g" -i FILE
Run Code Online (Sandbox Code Playgroud)

  • 在我的特定情况下,$2 是一个文件路径,因此 `sed` 由于解释 $2 内容中的 `/` 而导致呕吐。这正是我克服它所需要的。谢谢你的好提示! (2认同)

Tha*_*lin 47

另一种简单的选择

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

sed -e "s|xxx|$PWD|"
Run Code Online (Sandbox Code Playgroud)

  • 您说"使用双引号的替代方法",但您的示例使用双引号? (4认同)

yur*_*hen 15

?. 坏方法:更改分隔符

sed 's/xxx/'"$PWD"'/'
sed 's:xxx:'"$PWD"':'
sed 's@xxx@'"$PWD"'@'
Run Code Online (Sandbox Code Playgroud)

也许那些不是最终答案,

你不知道什么字符会出现在 $PWD, / :OR 中@

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

?. 好方法:转义分隔符

例如:尝试替换URL为 $url(有: /内容)

x.com:80/aa/bb/aa.js
Run Code Online (Sandbox Code Playgroud)

在字符串 $tmp

<a href="URL">URL</a>
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

或者

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>
Run Code Online (Sandbox Code Playgroud)


Edd*_*die 13

编辑问题后,我会看到您的问题.假设当前目录是/home/yourname ...在这种情况下,您的命令如下:

sed 's/xxx/'$PWD'/'
Run Code Online (Sandbox Code Playgroud)

将扩大到

sed `s/xxx//home/yourname//
Run Code Online (Sandbox Code Playgroud)

这是无效的.如果你想这样做,你需要在你的$ PWD中放一个\角色/.


小智 6

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

\n


Psy*_*ata 5

VAR=8675309
echo "abcde:jhdfj$jhbsfiy/.hghi$jh:12345:dgve::" |\
sed 's/:[0-9]*:/:'$VAR':/1' 
Run Code Online (Sandbox Code Playgroud)

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