如何在sed中转义斜杠、双引号和单引号?

112

根据我所了解的,当使用单引号时,内部的所有内容都被视为字面量。我想在我的替换中也是这样。但我还想找到一个既包含单引号又包含双引号的字符串。

例如:

sed -i 's/"http://www.fubar.com"/URL_FUBAR/g'
我想用URL_FUBAR替换"http://www.fubar.com"。sed如何识别我的//或双引号? 谢谢任何帮助! 编辑:我能使用`s/\"http\:\/\/www\.fubar\.\com\"/URL_FUBAR/g`吗? 单引号内的反斜杠实际上会转义字符吗?

大多数答案都集中在替换部分。对于匹配,请使用“引用转义引号” '\''(请参见 https://dev59.com/fnVD5IYBdhLWcg3wGHiu#91176)。 - Skippy le Grand Gourou
11个回答

133

sed中的s///命令允许您使用其他字符作为定界符,例如:

sed 's#"http://www\.fubar\.com"#URL_FUBAR#g'
或者
sed 's,"http://www\.fubar\.com",URL_FUBAR,g'

双引号不是问题。若要匹配单引号,请将这两种引号类型切换。请注意,一个用单引号引起来的字符串不能包含单引号(即使是转义过的也不行)。

如果希望sed按照字面意义解释点号而不是正则表达式模式.(即匹配任意单个字符),则需要对点号进行转义。


很好的回答,伙计。我只有一个快速问题。如果我想用单引号代替双引号,该怎么办?我的代码中有时会使用单引号或双引号,我可以运行两次此命令,但如何转义单引号的语法是什么? - KRB
转义单引号在我的Mac上的Bash中无法正常工作,但是使用不同的引号类型来包装命令,而不是要替换的引号,则可以正常工作。例如:使用sed 's/"/bla/g'"替换为bla或使用sed "s/'/bla/g"'替换为bla - rrr
5
单引号字符串中不能包含单引号。更改外部引号(并转义 shell 可能感兴趣的任何特殊字符)是解决这个问题的一种方法。另一种方法是在单引号字符串中断开,并使用 "'" (双引号表示单引号) 将字符串连接起来,然后继续单引号字符串的其余部分。例如:'you'"'"'d better do that'`。 - Kusalananda

41

关于单引号,查看以下代码,用于替换字符串 let'slet us

命令:

echo "hello, let's go"|sed 's/let'"'"'s/let us/g'

结果:

你好,让我们走吧


3
有一种更简单的方法来做这件事。尝试使用:echo "hello, let's go" | sed s/let\'s/let us/g。实际上,您不必将 sed 的参数放在单引号中。 - Tripp Kinetics

22

我的问题是需要将""放在表达式外面,因为sed表达式本身包含动态变量。因此,实际的解决方案是来自lenn jackman的方法,用[\"]替换sed正则表达式中的"

所以我的完整Bash命令是:

RELEASE_VERSION="0.6.6"

sed -i -e "s#value=[\"]trunk[\"]#value=\"tags/$RELEASE_VERSION\"#g" myfile.xml

这里是:

# 是sed分隔符

[\"] = " 在正则表达式中

value = \"tags/$RELEASE_VERSION\" = 我的替换字符串,请注意它只有一个\"作为引号


在我的情况下需要使用方括号。谢谢。 - Kent Bull

13

在单引号中使用单引号很难避免。试试这个:

sed "s@['\"]http://www.\([^.]\+).com['\"]@URL_\U\1@g" 

示例:

$ sed "s@['\"]http://www.\([^.]\+\).com['\"]@URL_\U\1@g" <<END
this is "http://www.fubar.com" and 'http://www.example.com' here
END

生成

this is URL_FUBAR and URL_EXAMPLE here

2

在sed中,转义双引号可能是必要的,例如,如果您在整个sed表达式中使用双引号(当您想要使用Shell变量时需要这样做)。

以下是一个示例,涵盖了在sed中转义和捕获bash中其他引用问题的一些内容:

# cat inventory
PURCHASED="2014-09-01"
SITE="Atlanta"
LOCATION="Room 154"

假设您想使用sed脚本更改房间,以便您可以反复使用,因此您将输入变量化如下:

# i="Room 101" (these quotes are there so the variable can contains spaces)

这个脚本会在文本中加入整行,如果该行不存在,或者使用sed命令替换该行为文本和$i的值。

if grep -q LOCATION inventory; then 
## The sed expression is double quoted to allow for variable expansion; 
## the literal quotes are both escaped with \ 
    sed -i "/^LOCATION/c\LOCATION=\"$i\"" inventory
## Note the three layers of quotes to get echo to expand the variable
## AND insert the literal quotes
else 
    echo LOCATION='"'$i'"' >> inventory
fi

P.S. 我将上述脚本分成多行以便于解析注释,但我在命令行中使用它作为一行,如下所示:

i="your location"; if grep -q LOCATION inventory; then sed -i "/^LOCATION/c\LOCATION=\"$i\"" inventory; else echo LOCATION='"'$i'"' >> inventory; fi

2

附注:包含BASH变量的sed表达式需要使用双引号(")引用才能正确解释变量。

如果您也将$BASH变量用双引号括起来(建议做法)

...然后你可以像下面这样转义变量双引号:

sed -i "s/foo/bar ""$VARIABLE""/g" <file>

即用""替换与$VARIABLE相关联的"。(简单地将"$VAR"转义为\"$VAR\"会导致输出字符串带有"引号。)

示例

$ VAR='apples and bananas'
$ echo $VAR
apples and bananas

$ echo "$VAR"
apples and bananas

$ printf 'I like %s!\n' $VAR
I like apples!
I like and!
I like bananas!

$ printf 'I like %s!\n' "$VAR"
I like apples and bananas!

这里,$VAR在管道传输到sed之前被"引用(sed会被'"引用):
$ printf 'I like %s!\n' "$VAR" | sed 's/$VAR/cherries/g'
I like apples and bananas!

$ printf 'I like %s!\n' "$VAR" | sed 's/"$VAR"/cherries/g'
I like apples and bananas!

$ printf 'I like %s!\n' "$VAR" | sed 's/$VAR/cherries/g'
I like apples and bananas!

$ printf 'I like %s!\n' "$VAR" | sed 's/""$VAR""/cherries/g'
I like apples and bananas!

$ printf 'I like %s!\n' "$VAR" | sed "s/$VAR/cherries/g"
I like cherries!

$ printf 'I like %s!\n' "$VAR" | sed "s/""$VAR""/cherries/g"
I like cherries!

将其翻译为中文:

与此相比:

$ printf 'I like %s!\n' $VAR | sed "s/$VAR/cherries/g"
I like apples!
I like and!
I like bananas!


$ printf 'I like %s!\n' $VAR | sed "s/""$VAR""/cherries/g"
I like apples!
I like and!
I like bananas!

我建议作为标准实践,对于BASH变量("$VAR")使用"-引号。

如果这些变量在sed表达式中使用(该表达式本身必须使用"-引号,而不是'-引号),则再次使用"-引号。

$ VAR='apples and bananas'

$ echo "$VAR"
apples and bananas

$ printf 'I like %s!\n' "$VAR" | sed "s/""$VAR""/cherries/g"
I like cherries!


2

对我最终有效的方法是使用sed的HEX选项来表示:

单引号:

echo "book'" |sed -n '/book[\x27]/p'

book'

双引号解决方案

cat testfile

"http://www.fubar.com"

sed -i 's|"http://www\.fubar\.com"|URL_FUBAR|g' testfile

cat testfile

URL_FUBAR


这是对sed来说最干净的解决方案。在双引号中使用'\x22'。 - undefined

0

你可以使用 %

sed -i "s%http://www.fubar.com%URL_FUBAR%g"

0
Prompt% cat t1
This is "Unix"
This is "Unix sed"
Prompt% sed -i 's/\"Unix\"/\"Linux\"/g' t1
Prompt% sed -i 's/\"Unix sed\"/\"Linux SED\"/g' t1
Prompt% cat t1
This is "Linux"
This is "Linux SED"
Prompt%

只需在双引号之前使用(反斜杠),并使用-i选项。 - SachinH
1
虽然这段代码片段很受欢迎,可能会提供一些帮助,但如果它包括了解释如何解决问题的说明,那将会大有改进。没有这个,你的答案就会少很多教育价值 - 记住,你正在回答未来读者的问题,而不仅仅是现在提问的人!请编辑你的答案添加解释,并指出适用的限制和假设。 - Toby Speight

-5

您需要使用\"来转义双引号字符(\转义后面的字符)

sed -i 's/\"http://www.fubar.com\"/URL_FUBAR/g'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接