Answers:
使用替代的正则表达式定界符,因为sed
您可以使用任何定界符(包括控制字符):
sed "s~$var~replace~g" $file
$var
一个纯bash的答案:使用参数扩展来反斜杠转义变量中的任何斜杠:
var="/Users/Documents/name/file"
sed "s/${var//\//\\/}/replace/g" $file
${parameter/pattern/string}
。因此,在这种情况下,参数为var
,模式为/\/
,字符串为\\/
。模式的所有实例都将替换,因为模式以开头/
。
使用/
在sed与变量中的斜杠分隔符的意志发生冲突时取代,因此你会得到一个错误。规避此问题的一种方法是使用另一个分隔符,该分隔符对于该变量中的任何字符都是唯一的。
var="/Users/Documents/name/file"
您可以使用适合情况的八字形字符(或其他任何不/
便于使用的字符)
sed "s#$var#replace#g"
要么
sed 's#$'$var'#replace#g'
当变量不包含空格时,这是合适的
要么
sed 's#$"'$var'"#replace#g'
使用上面的方法是比较明智的,因为与只对整个命令加双引号相比,我们有兴趣只用该变量中的任何内容来代替,因为整个命令可能会使您的shell插入可能被视为shell特殊shell字符的任何字符。
$var
包含~
,显然您将需要选择其他定界符。“未终止”错误听起来像您$var
包含换行符;您可以通过在值中的每个换行符后加反斜杠来解决此问题,但我认为这不是完全可移植的。基本上,这与价值的削减问题无关。
sed -i "s~blah~$var~g" file
仅在实际sed
脚本周围加上引号。
这是一个古老的问题,但是这里没有任何答案s/from/to/
会详细讨论操作。
sed
声明的一般形式是
*address* *action*
其中address可以是正则表达式范围或行号范围(或为空,在这种情况下,该操作将应用于每个输入行)。所以举个例子
sed '1,4d' file
将删除第1至4行(地址是行号范围1,4
,而动作是d
delete命令);和
sed '/ick/,$s/foo/bar/' file
将在regex上的第一个匹配项与文件末尾之间的任何行上foo
用替换第bar
一个匹配项ick
(地址是范围/ick/,$
,而动作是replace 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
或者,如果您使用其他外壳,请尝试
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
在第二。
使用Perl,其中变量是一等公民,而不仅仅是扩展宏:
var=/Users/Documents/name/file perl -pe 's/\Q$ENV{var}/replace/g' $file
-p
逐行读取输入并在处理后打印该行\Q
引用以下字符串中的所有元字符(此处显示的值不需要,但如果包含的值[
或某些其他常规表达式专用的值,则是必需的)