关于正则表达式:如何将包含斜杠的变量传递给sed

How to pass a variable containing slashes to sed

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

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

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

我想这样将其传递给sed

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

但是我得到了错误。 我该如何解决这个问题?


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

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


一个纯bash的答案:使用参数扩展来反斜杠转义变量中的任何斜杠:

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


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

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

然后,这将起作用:

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

在sed中使用/作为分隔符将在替换时与变量中的斜杠冲突,结果您将得到一个错误。避免这种情况的一种方法是使用另一个分隔符,该分隔符对于该变量中的任何字符都是唯一的。

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

您可以使用适合情况的八字形字符(或其他不是/的其他字符以方便使用)

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

要么

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

当变量不包含空格时,这是合适的

要么

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

使用上面的方法是比较明智??的,因为与只对整个命令加双引号相比,我们有兴趣只用该变量中的任何内容来代替,因为整个命令可能会使您的shell插入可能被视为shell特殊shell字符的任何字符。


这是一个古老的问题,但是除了s/from/to/以外,这里没有其他答案会详细讨论操作。

sed语句的一般形式是

1
*address* *action*

其中address可以是正则表达式范围或行号范围(或为空,在这种情况下,该操作将应用于每个输入行)。所以举个例子

1
sed '1,4d' file

将删除第1至4行(地址是行号范围1,4,操作是d delete命令);和

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

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

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

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

(请注意,请使用双引号而不是单引号,以便外壳程序可以对变量进行插值,并且必须在双引号内使用文字美元符号进行引号),但是如果变量包含斜杠,则会出现语法错误。 (shell扩展变量,然后将结果字符串传递给sed;因此sed仅看到文字文本-它没有shell变量的概念。)

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

1
sed"\\\\%$variable%,\\$s/foo/bar/" file

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

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

或者,如果您使用其他外壳,请尝试

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

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

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

在第一种情况下,以及

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

在第二。


使用Perl,其中变量是一等公民,而不仅仅是扩展宏:

1
var=/Users/Documents/name/file perl -pe 's/\\Q$ENV{var}/replace/g' $file

  • -p逐行读取输入并在处理后打印该行
  • \\Q引用以下字符串中的所有元字符(此处显示的值不需要此字符,但是如果该值包含[或某些其他常规表达式专用值,则必须使用)