Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex 如何将包含斜杠的变量传递给sed_Regex_Bash_Sed - Fatal编程技术网

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

Regex 如何将包含斜杠的变量传递给sed,regex,bash,sed,Regex,Bash,Sed,如何将包含斜杠的变量作为模式传递给sed 例如,如果我有以下变量: var="/Users/Documents/name/file" var="/Users/Documents/name/file" sed "s/${var//\//\\/}/replace/g" $file 我想将其传递给sed,如下所示: sed "s/$var/replace/g" "$file" 然而,我得到了错误。如何避免此问题?使用备用正则表达式分隔符,因为sed允许您使用任何分隔符(包括控制字符)): 纯ba

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

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

var="/Users/Documents/name/file"
var="/Users/Documents/name/file"
sed "s/${var//\//\\/}/replace/g" $file
我想将其传递给
sed
,如下所示:

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

然而,我得到了错误。如何避免此问题?

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

纯bash答案:用于反斜杠转义变量中的任何斜杠:

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

另一种方法是使用另一个
sed
命令避开
var
中的所有反斜杠,尽管比anubhava的答案更难看:

var=$(echo "$var" | sed 's/\//\\\//g')
然后,这将起作用:

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

在sed中使用
/
作为分隔符将在替换时与变量中的斜杠冲突,因此会出现错误。避免这种情况的一种方法是使用另一个分隔符,该分隔符与该变量中的任何字符都是唯一的

var="/Users/Documents/name/file"
您可以使用适合场合的octothorpe字符(或任何其他非
/
字符,以便于使用)

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


使用上述命令更明智,因为我们只想替换该变量中的任何内容,而不是重复引用整个命令,这会导致shell将可能被视为特殊shell字符的任何字符插入shell。

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

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

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

sed
语句的一般形式为

*address* *action*
其中地址可以是正则表达式范围或行号范围(或空,在这种情况下,操作应用于每个输入行)

sed '1,4d' file
将删除第1行到第4行(地址是行号范围
1,4
,操作是
d
delete命令);以及

将在正则表达式
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

在第二个中。

不起作用。我尝试sed-I“s~blah~$var~g文件”,得到:“sed-e表达式#1,char 70:unterminated`s'命令”。我已经确认,罪魁祸首是$var中的斜杠。这种解决方案的变体到处都是,而且都不起作用。sed最近更新了吗?我在Ubuntu 14.04.4 LTS的v4.2.2上。这取决于
$var
的值是多少。@PaulEricson观察到,~不起作用,但仍然适用于最后一个“~”(g之后)似乎不需要,至少对于AWS Amazon Linux(基于CentOS)而言,我终于在这里找到了答案…谢谢!!不起作用。我尝试了sed-I“s~blah~$var~g file”并得到:“sed-e expression#1,char 70:unterminated`s'命令”。我已经确认罪魁祸首是$var中的斜杠。这个解决方案的变体到处都是,没有一个有效。sed最近更新了吗?我在Ubuntu 14.04.4 LTS上的v4.2.2上。@PaulEricson我无法在任何可用的Ubuntu上重新编程。如果你的
$var
包含
~
,你显然需要pick另一个分隔符。“未终止”错误听起来像是您的
$var
包含一个换行符;您可以通过反斜杠转义值中的每一个换行符来修复它,但我不认为这是完全可移植的。这大体上与值中的斜杠问题无关。@PaulEricson哦,而且您的引号是不正确的,您不应该在引号中包含文件名.
sed-i“s~blah~$var~g”文件
仅在实际的
sed
脚本周围加引号。这是一种很好的方法,因为您并不总是知道变量包含哪些字符。因此,如果有疑问,您总是可以转义sed分隔符。例如:sed“s:${var/://\\:}:replace:g”$FileBeauty。使我的一些重命名脚本更干净。今天学到了一些漂亮的东西,谢谢。这应该是公认的答案。这里使用的模式更清晰:
${parameter/pattern/string}
。因此,在本例中,参数是
var
,模式是
/\/
,字符串是
\/
escaped=$(echo "$variable" | sed 's%/%\\/%g')
sed "s/$escaped/,\$s/foo/bar/" file
sed '\%1/2%,$s/foo/bar/' file
sed '/1\/2/,$s/foo/bar/' file