sed 中的单引号和双引号

sed 中的单引号和双引号

我在 sed 中测试了单引号和双引号

me@host:~:
$ echo "front" | sed "s/front/back/"
back
me@host:~:
$ echo "front" | sed 's/front/back/'
back

它们的性能相同,但我记得几个月前读到过它们之间存在差异。

Google 搜索对关键字“sed 中的单引号和双引号”没有帮助。

它们并不完全相同,对吗?

答案1

我正在将我之前的评论扩展为答案。

我的建议是坚持使用单引号,除非你知道自己在做什么,并且需要利用某些命令行功能。想到的最常见的情况是文本字符串中的单引号和 shell 变量插值。

以下几个例子充分说明了使用双引号的合理性:

$ echo "We're good!" | sed "s/'re/ are/"
We are good!

$ name="John"; echo "Hello, I'm <name>." | sed "s/<name>/$name/"
Hello, I'm John.

双引号似乎可以实现一些不错的功能,那么为什么不一直使用它们呢?对我来说,主要原因是无法始终看到 实际执行的命令sed。当命令括在单引号中时,情况非常简单:您看到的就是所sed看到的。但是,当使用双引号时,您的字符串将在传递给 之前由 shell 进行解释sed,并且您必须考虑任何修改,其中一些可能不是您想要的。这是一个很好的例子:

$ echo 'SELECT `date` FROM `services`' | sed 's/`date`/`uptime`/'
SELECT `uptime` FROM `services`

如果您使用双引号,那么您的实际sed命令将是这样的:

$ sed "s/`date`/`uptime`/"
$ sed 's/Wed May 29 08:28:20 UTC 2019/ 08:28:20 up 13 days,  1:29,  1 user,  load average: 0.08, 0.02, 0.00/'

在与 连接时,通常可以使用双引号sed,因为该符号的使用$往往不含糊:

$ line="back"; echo "front" | sed "s/front$/$line/"
back
$ line="back"; echo "frontline" | sed "s/front$/$line/"
frontline
$ line="-line"; echo "front-line" | sed "s/front$line/back$line/"
back-line

如果您正在编写awkperl,事情会变得更加复杂,其中$有更多用途:

$ echo "col1 col2 col3" | awk '{print $1}'
col1
$ echo "col1 col2 col3" | awk "{print $1}"
col1 col2 col3

$ echo "col1 col2 col3" | perl -lane 'print $F[0]'
col1
$ echo "col1 col2 col3" | perl -lane "print $F[0]"
ARRAY(0x564346f18db0)

答案2

这实际上与 bash 相关,而不仅仅是命令sed

通过查看此示例你可以更好地理解它:

~ $ front="front"
~ $ echo "front" | sed "s/$front/back/"
back
~ $ echo "front" | sed 's/$front/back/'
front

双引号计算其中的表达式,而单引号保留每个字符的字面值。更多信息请见此处:https://stackoverflow.com/questions/6697753/difference-between-single-and-double-quotes-in-bash

答案3

再分享一个例子来说明单引号和双引号造成的不同结果。

当有反斜杠时,单个是不够的,需要\另一个来转义,即\\

$ echo "\alpha" | sed 's/\\alpha/\\beta/'
\beta

但对于双引号,我们需要三个引号,

$ echo "\alpha" | sed "s/\\alpha/\\beta/"
\alpha
$ echo "\alpha" | sed "s/\\\alpha/\\\beta/"
\beta

因为\在 shell 中解释时已经用完了一个。

此外,如果我们想在给定的字符串之前插入,还\需要一个,

$ echo "\alpha" | sed '/alpha/i \\\beta'
\beta
\alpha

原因我不太清楚,但根据手册,\命令后面确实有一个i

       i \

       text   Insert text, which has each embedded newline preceded by a backslash.

而对于双引号,则需要两个反斜杠,

$ echo "\alpha" | sed "/alpha/i \\\\\beta"
\beta
\alpha

相关内容