如何将包含斜杠的变量作为模式传递给sed
?
例如,如果我有以下变量:
var="/Users/Documents/name/file"
我想将其传递给sed
,因为:
sed "s/$var/replace/g" "$file"
然而我收到错误。我该如何规避这个问题?
答案 0 :(得分:133)
使用备用正则表达式分隔符,sed
允许您使用任何分隔符(包括控制字符):
sed "s~$var~replace~g" $file
答案 1 :(得分:38)
一个纯粹的bash回答:使用parameter expansion反斜杠 - 转义变量中的任何斜杠:
var="/Users/Documents/name/file"
sed "s/${var//\//\\/}/replace/g" $file
答案 2 :(得分:25)
另一种方法,虽然比anubhava的答案更丑陋,但是使用另一个var
命令转义sed
中的所有反斜杠:
var=$(echo "$var" | sed 's/\//\\\//g')
然后,这将有效:
sed "s/$var/replace/g" $file
答案 3 :(得分:10)
在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字符的字符插入
答案 4 :(得分:5)
这是一个古老的问题,但是这里的答案都没有详细讨论s/from/to/
以外的其他操作。
sed
语句的一般形式是
*address* *action*
其中 address 可以是正则表达式范围或行号范围(或为空,在这种情况下, action 应用于每个输入行)。例如
sed '1,4d' file
将删除第1至4行(地址是行号范围1,4
,而 action 是d
delete命令);和
sed '/ick/,$s/foo/bar/' file
在正则表达式foo
的第一个匹配项和文件结尾(地址之间的任何行上,将bar
的第一个匹配项用ick
替换>是范围/ick/,$
,而 action 是s
替代命令s/foo/bar/
)。
在这种情况下,如果ick
来自变量,则可以
sed "/$variable/,\$s/foo/bar/"
(请注意使用双引号而不是单引号,以便外壳程序可以对变量进行插值,并且必须在双引号内使用文字美元符号),但是如果变量包含斜杠,则会出现语法错误。 (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
第二个。
答案 5 :(得分:2)
使用Perl,变量是一等公民,而不仅仅是扩展宏:
var=/Users/Documents/name/file perl -pe 's/\Q$ENV{var}/replace/g' $file
-p
逐行读取输入并在处理后打印该行\Q
引用以下字符串中的所有元字符(此处显示的值不需要该字符,但如果该值包含[
或其他一些常规表达式的特殊值,则是必需的)