我们什么时候应该使用引号?

我们什么时候应该使用引号?

我刚刚开始学习 Bash,因此对于以下可能看起来过于基础的问题,我深感抱歉。

我很难理解 Shell 脚本中引号的使用。

如果我要写

a="file"
b="`grep " a" "$a"`"
echo $b
  1. 它们应该在引号“`grep " a" "$a"`" 中被读作“$a”和“a”吗?

    或者,它是从左到右读的?

    因为我被教导用双引号将变量括起来。

    更让我困惑的是,我的老师告诉我,为了防止系统误解变量名及其后面的文本,我们应该在变量名周围添加另一个双引号。

  2. 嵌套引号有什么作用?我们什么时候应该使用引号?

答案1

普通引号不能嵌套,但反引号在双引号中比较特殊。

使用它$()代替反引号更具可读性和更简洁。它们的意思都是命令替换,即它们扩展到它们所包含的命令的输出。

b="$(grep " a" "$a")"

但是您不需要在赋值中使用外部双引号,因此以下内容是等效的:

b=$(grep " a" "$a")

您的问题已更改,因此让我们添加更多详细信息:您应该在想要防止分词的任何地方使用双引号。变量名称的问题最好地证明在

echo "$var1_$var2"    # two variables, $var1_ and $var2
echo "$var1"_"$var2"  # two variables, $var1 and $var2, separated by an underscore
# also possible:
echo "${var1}_$var2"

答案2

由于您使用了带有反引号的命令替换的古老形式,因此答案是“这取决于”。某些 shell(例如 Bash)使用反引号启动一个新的引用上下文,因此内部双引号对嵌套在反引号和外部双引号内,最终得到以下四个引用部分:

b="`grep " a" "$a"`"
#        c--c d--d
#  b--------------b
# a----------------a

但是...其他一些 shell (ksh) 会对其进行解析,以便第二个双引号结束双引号字符串,而不管中间的反引号如何。结果是这样的:

b="`grep " a" "$a"`"
# a------a  b-b  c-c

这并不能达到你想要的效果。(它运行grep '',将其输出分配给b,然后运行a​​,并使用由空命令替换给出的参数。)

看:ksh 中的反引号内的引号

毫不奇怪,POSIX 没有定义这种情况。


也就是说,如果您要更改为使用$(...)命令替换的形式,您将避免这种情况,并且在这种情况下,扩展总是启动一个新的引用上下文,因此它嵌套在双引号内,并且双引号内内巢内$(...)

b="$(grep " a" "$a")"
#         c--c d--d
#   b--------------b
# a-----------------a

看:

请记住,朋友不要让朋友使用反引号。


更让我困惑的是,我的老师告诉我,为了防止系统误解变量名及其后面的文本,我们应该在变量名周围添加另一个双引号。

为此,您可以使用引号,或在变量名称两边加上大括号。因此,在所有三种变体中,下面都$foo进行了扩展并附加了固定字符串bar

$ foo=xxx
$ echo "$foo""bar" "$foo"bar "${foo}bar" 
xxxbar xxxbar xxxbar

最后一篇可能是最容易阅读的。

嵌套引号有什么作用?我们什么时候应该使用引号?

如上所述,如果没有命令替换之类的内容,引号不会相互嵌套。如果没有一个,类似的引号只是结束引用,而其他引号就像普通字符一样,不引用任何内容。

例如,这是两个带引号的字符串,中间有一个不带引号的部分:

  "foo "abc def" bar"
# <---->       <---->
#          ^ unquoted space.

这是一个带引号的字符串,恰好包含单引号字符:

$ echo "foo 'abc def' bar"
foo 'abc def' bar

echo单引号作为命令行参数的一部分传递,就像字母和空格一样。他们不引用任何内容。

至于什么时候,请看:什么时候需要双引号?

相关内容