Contents

什么时候在shell命令中包装引号

1. 简介

作为 Linux 生态系统的初学者,我们可能会在网上阅读的几个命令中遇到参数。有时,我们将这些参数用双引号括起来,有时用单引号括起来,有时我们根本不将它们用引号括起来。在本文中,我们将研究可能使用或省略不同引号的各种场景, 并了解引号的工作原理。

2. 带空格的字符串

我们有文字字符串或其中包含空格的参数的情况下,我们可以使用单引号或双引号来包装整个字符串,以将其视为单个参数。我们可以使用 expr 命令来试试这个:

$ expr length "hello world"
11
$ expr length 'hello world'
11
$ expr length hello world
expr: syntax error: unexpected argument ‘world’

当我们使用单引号或双引号时,“hello world”被视为单个参数,长度计算为 11。当我们省略引号时,“hello”和“world”被视为单独的参数,命令抛出一个错误,因为它期望长度操作只有一个参数。

3. 控制变量插值

当我们使用双引号或省略引号时会发生变量插值。**当我们需要抑制变量插值时,我们将参数用单引号括起来。**我们可以通过几个例子看到这一点:

$ a=hello
$ b=world
$ echo $a
hello
$ echo "$a"
hello
$ echo "$a $b"
hello world
$ echo '$a $b'
$a $b

在上面的示例中,我们定义了两个变量,“a”和“b”,当我们使用双引号或省略引号时,我们看到它们的值被替换。当我们使用单引号时,变量名称会逐字打印,因为不会发生替换。

4. 命令替换

与变量插值类似,命令替换仅在我们在双引号内执行或省略引号时才有效。单引号将逐字采用参数。让我们尝试一些命令来看看它是如何工作的:

$ echo "$(ls /usr/share/dict)"
american-english
british-english
README.select-wordlist
words
words.pre-dictionaries-common
$ echo $(ls /usr/share/dict)
american-english british-english README.select-wordlist words words.pre-dictionaries-common
$ echo '$(ls /usr/share/dict)'
$(ls /usr/share/dict)

从上面的例子可以看出,当我们使用双引号或者省略双引号时,会执行大括号内的命令,并打印结果。当我们使用单引号时,不会执行命令,但会逐字打印参数。

5. 控制文件通配

我们可以使用单引号或双引号来抑制文件通配。如果我们需要文件 globbing 工作,我们需要省略引号

$ cat *
file1 contents
file2 contents
file3 contents
$ cat "*"
cat: '*': No such file or directory
$ cat '*'
cat: '*': No such file or directory
$ cat "my dir/"*
file1 contents
file2 contents
file3 contents
$ cat my dir/*
cat: my: No such file or directory
cat: 'dir/*': No such file or directory

从上面的示例中,我们还注意到我们可以将空格括在引号中,并将通配符放在引号之外以执行通配符。这适用于单引号和双引号。

6.保护引号和特殊字符

我们可以使用单引号来保护双引号,反之亦然

$ echo he'll'o
hello
$ echo he"ll"o
hello
$ echo 'he"ll"o'
he"ll"o
$ echo "he'll'o"
he'll'o

在上面的示例中,我们看到字符串中的引号仅在整个字符串被引号包裹时才被保留。我们还可以选择在单引号前包含一个 $ 符号,以便根据其含义解释转义序列。此外,我们可以使用它来保护同一字符串中的单引号和双引号:

$ echo "hello\nworld"
hello\nworld
$ echo 'hello\nworld'
hello\nworld
$ echo $'hello\nworld'
hello
world
$ echo $'\'single quoted text\' and "double quoted text"'
'single quoted text' and "double quoted text"

7.控制分词

**要执行分词,我们需要省略引号。**当我们添加引号时,不会发生拆分,整个字符串作为一个单元处理:

$ for word in one two three; do echo $word; done
one
two
three
$ for word in "one two three"; do echo $word; done
one two three
$ for word in 'one two three'; do echo $word; done
one two three

在第一种情况下,循环运行三次,因为发生了单词拆分并产生三个单词,而在后一种情况下,循环只运行一次,整个字符串作为值。