如何将包含斜杠的变量传递给 sed

How to pass a variable containing slashes to sed

如何将包含斜杠的变量作为模式传递给 sed

例如,如果我有以下变量:

var="/Users/Documents/name/file"

我想这样传递给sed:

sed "s/$var/replace/g" "$file"

但是我遇到了错误。我怎样才能避免这个问题?

使用备用正则表达式定界符,因为 sed 允许您使用任何定界符(包括控制字符):

sed "s~$var~replace~g" $file

如上所述,我们也可以使用控制字符作为分隔符,如:

sed "s^[$var^[replace^[g" file

其中 ^[ 是通过同时按下 Ctrl-V-3 来输入的。

否则在 bash shell 中,您可以使用此 sed</code> 作为分隔符:</p> <pre><code>d=$'' sed "s${d}$var${d}replace$d" file

一个纯粹的 bash 答案:使用 parameter expansion 反斜杠转义变量中的任何斜杠:

var="/Users/Documents/name/file"
sed "s/${var//\//\/}/replace/g" $file

另一种方法,虽然比 anubhava 的答案更难看,但是使用另一个 sed 命令转义 var 中的所有反斜杠:

var=$(echo "$var" | sed 's/\//\\//g')

那么,这将起作用:

sed "s/$var/replace/g" $file

在 sed 中使用 / 作为分隔符将在替换时与变量中的斜杠冲突,因此您将收到错误消息。避免这种情况的一种方法是使用另一个定界符,该定界符不同于该变量中的任何字符。

var="/Users/Documents/name/file"

您可以使用适合场合的 octothorpe 字符(或任何其他不是 / 的字符以便于使用)

sed "s#$var#replace#g" 

sed 's#$'$var'#replace#g'

适用于变量不包含空格的情况

sed 's#$"'$var'"#replace#g'

使用上面的方法更明智,因为我们只对替换该变量中的任何内容感兴趣,而不是双引号整个命令,这可能导致您的 shell 插入任何可能被认为是shell.

的特殊 shell 字符

使用 Perl,其中变量首先是 class 公民,而不仅仅是扩展宏:

var=/Users/Documents/name/file perl -pe 's/\Q$ENV{var}/replace/g' $file
  • -p逐行读取输入,处理后打印行
  • \Q 引用以下字符串中的所有元字符(此处显示的值不需要,但如果值包含 [ 或其他一些特殊的正则表达式值则需要)

这是一个老问题,但是这里 none 的答案详细讨论了 s/from/to/ 以外的操作。

sed 语句的一般形式是

*address* *action*

其中 address 可以是正则表达式范围或行号范围(或为空,在这种情况下 action 应用于每个输入线)。例如

sed '1,4d' file

将删除第 1 行到第 4 行(address 是行号范围 1,4actiond删除命令);和

sed '/ick/,$s/foo/bar/' file

将在正则表达式 ick 的第一个匹配项和文件结尾( 之间的任何行上用 bar 替换第一次出现的 foo地址 是范围/ick/,$ 动作s 替代命令s/foo/bar/).

在这种情况下,如果 ick 来自变量,您可以

sed "/$variable/,$s/foo/bar/"

(注意使用双引号而不是单引号,这样 shell 可以插入变量,并且必须在双引号内引用文字美元符号)但是如果变量包含斜杠,你会得到一个语法错误。 (shell 扩展变量,然后将结果字符串传递给 sed;因此 sed 只能看到文字文本——它没有 shell 变量的概念。)

解决方法是使用不同的分隔符(显然您需要能够使用不能出现在变量值中的字符),但与 s%foo%bar% 情况不同的是,您还需要一个反斜杠如果您想使用与默认 /:

不同的分隔符,则在分隔符之前
sed "\%$variable%,$s/foo/bar/" file

(在单引号内,一个反斜杠显然就足够了);或者您可以单独转义值中的每个斜线。此特定语法仅 Bash:

sed "/${variable//\//\/}/,$s/foo/bar/" file

或者如果您使用不同的 shell,请尝试

escaped=$(echo "$variable" | sed 's%/%\/%g')
sed "s/$escaped/,$s/foo/bar/" file

为清楚起见,如果 $variable 包含字符串 1/2,则上述命令等同于

sed '\%1/2%,$s/foo/bar/' file

第一种情况,

sed '/1\/2/,$s/foo/bar/' file

第二个