转义和引号

转义和引号

Bash 只有一种数据类型,就是字符串。不管用户输入什么数据,Bash 都视为字符串。因此,字符串相关的引号和转义,对 Bash 来说就非常重要。

转义和反斜杠

某些字符在 Bash 里面有特殊含义(比如 $&*)。Bash 在碰到这些字符的时候,会将其理解为其他意思,比如 $name 表示的是 name 这个变量,如果想要让 Bash 将其当作一个普通字符,不对其进行转义,就必须在这些特殊字符前面加上反斜杠,使其变成普通字符。这就加上反斜杠的操作叫做“转义”(escape)。

$ echo $name

$ echo *
aaa bbb ccc test.txt
$ echo \$name
$name
$ echo \*
*

因为 name 变量在当前环境没有定义,所以输出为空。

反斜杠本身也是特殊字符,想要输出反斜杠,也需要进行转义,\\

$ echo \\
\

反斜杠除了用于转义,还可以表示一些不可打印的字符。

如果想要在命令行中让这些不可打印字符表达出其特殊含义,可以把它们放在引号里面,然后使用 echo 命令的 -e 参数。

$ echo a\tb
atb
$ echo "a\tb"
a\tb
$ echo -e "a\tb"
a       b
$ echo -e "a\bb"
b
$ echo -e "a\nb"
a
b

换行符是一个特殊字符,表示命令的结束,Bash 收到这个字符以后,就会对输入的命令进行解释执行。换行符前面加上反斜杠转义,就使得换行符变成一个普通字符,即 \\n,Bash 会将其当作长度为 0 的空字符处理,从而可以将一行命令写成多行。这也是为什么通过在命令的末尾写 \ 可以将一行命令拆分成多行

$ echo hello \
> world \
> xiashuo.xyz
hello world xiashuo.xyz

单引号

Bash 允许字符串放在单引号或双引号之中,加以引用。

单引号用于保留字符的字面含义,各种特殊字符在单引号里面,都会变为普通字符,比如星号(*)、美元符号($)、反斜杠(\)等。包括 Bash 模式扩展字符,在单引号中都会失效

$ echo '

由于反斜杠在单引号里面变成了普通字符,所以如果单引号之中,还要使用单引号,不能使用转义,需要在外层的单引号前面加上一个美元符号(`$`),然后再对里层的单引号转义。不过这种下,我们一般在双引号中使用单引号

```shell
$ echo 'it's'
> ^C
$ echo 

## 双引号

双引号比单引号宽松,大部分特殊字符在双引号里面,都会失去特殊含义,变成普通字符,比如 `*`,这意味着,双引号里面不会进行文件名扩展。但是,三个特殊字符除外:美元符号(`$`)、反引号(`` ` ``)和反斜杠(`\`)。这三个字符在双引号之中,依然有特殊含义,会被 Bash 自动扩展。

在双引号中,美元符号用来引用变量,反引号则是执行子命令,反斜杠则是用来转义,以反斜杠开头的不可打印字符则会失效。

```shell
$ echo file{1..2}
file1 file2
$ echo "file{1..2}"
file{1..2}
$ echo "*"
*
$ echo "shell path: $SHELL"
shell path: /bin/bash
$ echo "date now : `date`"
date now : Mon Aug 14 17:19:14 CST 2023
$ echo "\"hello\" \"world\""
"hello" "world"

通过回车插入的换行符在双引号之中,会失去特殊含义,Bash 正常情况下会将换行符解释为命令结束,但是换行符在双引号之中就失去了这种特殊作用,只用来换行,所以可以输入多行。echo 命令会将换行符原样输出,显示的时候正常解释为换行。所以可以利用双引号,在命令行输入多行文本。

$ echo "hello
>
> world
> "
hello

world

但是你直接在双引号中手写 \n 是不行的

$ echo "hello\nworld"
hello\nworld

双引号的另一个常见的使用场合是,文件名包含空格。这时就必须使用双引号(或单引号),将文件名放在里面。否则 Bash 会将其理解为被被空格分割开的两个参数

双引号还有一个作用,就是保存原始命令的输出格式。

$ cal
     August 2023
Su Mo Tu We Th Fr Sa
       1  2  3  4  5
 6  7  8  9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31

$ echo $(cal)
August 2023 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
$ echo "$(cal)"
     August 2023
Su Mo Tu We Th Fr Sa
       1  2  3  4  5
 6  7  8  9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31

Here 文档

Here 文档(here document)是一种输入多行字符串的方法,格式如下:

<< token
text
token

它的格式分成开始标记(<< token)和结束标记(token)。开始标记是两个小于号加上 token,中间可以有空格也可以没有空格,token 可以随意取,后面必须是一个换行符;结束标记是单独一行顶格写的 token,如果不是顶格,结束标记不起作用。两者之间就是多行字符串的内容。

token 可以理解开始输入和结束输入的文本标记,阮一峰大佬说这是 Here 文档的名称,其实不合适

$ cat << file
> 111
> 222
> 333
> file
111
222
333

我们在 shell 脚本中创建文件并在其中填入内容的时候,经常使用 Here 文档。

$ cat > test.txt << _
> <html>
> <div>
> </div>
> </html>
> _
$ cat test.txt
<html>
<div>
</div>
</html>

在 Here 文档内部会发生变量解析,同时支持反斜杠转义,但是不支持通配符扩展,双引号和单引号也失去语法作用,变成了普通字符。

支持变量解析,让我们可以在脚本中根据变量动态地生成 Here 文档。

$ cat << EOF
> $name
> "$name"
> '$name'
> \$name
> *
> EOF
xiashuo.xyz
"xiashuo.xyz"
'xiashuo.xyz'
$name
*

如果不希望发生变量替换,可以把 Here 文档的开始标记放在单引号之中。(结束标记不用放到单引号中)

Here 文档的本质是重定向,它将文档重定向给了某个命令的标准输入,所以,Here 文档只适合那些可以接受标准输入作为参数的命令,比如 catgrep,有的命令不接受标准输入作为参数,比如 echo,所以 echo 命令无法配合 Here 文档。

关于标准输入跟命令行参数有什么区别,请看《Linux 文件系统基础》的 | 管道符号 小节

关于什么是重定向,请看《Linux 文件系统基础》的 >指令和>>指令 小节

重定向和管道还是有区别的,阮一峰大佬的 博客 中写到重定向等同于管道的说法是错误的

此外,Here 文档也不能作为变量的值,只能用于命令的参数。

Here 字符串

Here 文档还有一个变体,叫做 Here 字符串(Here string),使用三个小于号(<<<)表示。

<<< string

它的作用是将字符串通过标准输入,传递给命令。

有些命令直接接受给定的参数,与通过标准输入接受参数,结果是不一样的。所以才有了这个语法,使得将字符串通过标准输入传递给命令更方便,比如 cat 命令只接受标准输入传入的字符串。

$ cat hello world
cat: hello: No such file or directory
cat: world: No such file or directory
$ cat <<< 'hello world'
hello world
# 效果等同于 echo
$ echo hello world
hello world

效果等同于 echo hello world

echo 'namename
$ echo '*'
*
$ echo '(ls)(ls)
$ echo '((2+2))((2+2))
$ echo ''
\


由于反斜杠在单引号里面变成了普通字符,所以如果单引号之中,还要使用单引号,不能使用转义,需要在外层的单引号前面加上一个美元符号(`$`),然后再对里层的单引号转义。不过这种下,我们一般在双引号中使用单引号

{{CODE_BLOCK_5}}

## 双引号

双引号比单引号宽松,大部分特殊字符在双引号里面,都会失去特殊含义,变成普通字符,比如 `*`,这意味着,双引号里面不会进行文件名扩展。但是,三个特殊字符除外:美元符号(`$`)、反引号(`` ` ``)和反斜杠(`\`)。这三个字符在双引号之中,依然有特殊含义,会被 Bash 自动扩展。

在双引号中,美元符号用来引用变量,反引号则是执行子命令,反斜杠则是用来转义,以反斜杠开头的不可打印字符则会失效。

{{CODE_BLOCK_6}}

通过回车插入的换行符在双引号之中,会失去特殊含义,Bash 正常情况下会将换行符解释为命令结束,但是换行符在双引号之中就失去了这种特殊作用,**只用来换行**,所以可以输入多行。`echo` 命令会将换行符原样输出,显示的时候正常解释为换行。所以可以利用双引号,在命令行输入多行文本。

{{CODE_BLOCK_7}}

但是你直接在双引号中手写 `\n` 是不行的

{{CODE_BLOCK_8}}

双引号的另一个常见的使用场合是,文件名包含空格。这时就必须使用双引号(或单引号),将文件名放在里面。否则 Bash 会将其理解为被被空格分割开的两个参数

双引号还有一个作用,就是保存原始命令的输出格式。

{{CODE_BLOCK_9}}

## Here 文档

Here 文档(here document)是一种输入多行字符串的方法,格式如下:

{{CODE_BLOCK_10}}

它的格式分成开始标记(`<< token`)和结束标记(`token`)。开始标记是两个小于号加上 token,中间可以有空格也可以没有空格,token 可以随意取,后面必须是一个换行符;结束标记是单独一行顶格写的 token,如果不是顶格,结束标记不起作用。两者之间就是多行字符串的内容。

> token 可以理解开始输入和结束输入的文本标记,阮一峰大佬说这是 Here 文档的名称,其实不合适

{{CODE_BLOCK_11}}

我们在 shell 脚本中创建文件并在其中填入内容的时候,经常使用 Here 文档。

{{CODE_BLOCK_12}}

在 Here 文档内部会发生变量解析,同时支持反斜杠转义,但是不支持通配符扩展,双引号和单引号也失去语法作用,变成了普通字符。

> 支持变量解析,让我们可以在脚本中根据变量动态地生成 Here 文档。

{{CODE_BLOCK_13}}

如果不希望发生变量替换,可以把 Here 文档的开始标记放在单引号之中。(结束标记不用放到单引号中)

Here 文档的本质是重定向,它将文档重定向给了某个命令的标准输入,所以,Here 文档只适合那些可以接受标准输入作为参数的命令,比如 `cat`、`grep`,有的命令不接受标准输入作为参数,比如 `echo`,所以 `echo` 命令无法配合 Here 文档。

> 关于标准输入跟命令行参数有什么区别,请看《Linux 文件系统基础》的 `| 管道符号` 小节

> 关于什么是重定向,请看《Linux 文件系统基础》的 `>指令和>>指令` 小节
> 
> 重定向和管道还是有区别的,阮一峰大佬的 [博客](https://wangdoc.com/bash/quotation#here-%E6%96%87%E6%A1%A3) 中写到重定向等同于管道的说法是错误的

此外,Here 文档也不能作为变量的值,只能用于命令的参数。

## Here 字符串

Here 文档还有一个变体,叫做 Here 字符串(Here string),使用三个小于号(`<<<`)表示。

{{CODE_BLOCK_14}}

它的作用是将字符串通过标准输入,传递给命令。

**有些命令直接接受给定的参数,与通过标准输入接受参数,结果是不一样的**。所以才有了这个语法,使得将字符串通过标准输入传递给命令更方便,比如 `cat` 命令只接受标准输入传入的字符串。

{{CODE_BLOCK_15}}

效果等同于 `echo hello world`
it's'
> ^C
$ echo 

## 双引号

双引号比单引号宽松,大部分特殊字符在双引号里面,都会失去特殊含义,变成普通字符,比如 `*`,这意味着,双引号里面不会进行文件名扩展。但是,三个特殊字符除外:美元符号(`$`)、反引号(`` ` ``)和反斜杠(`\`)。这三个字符在双引号之中,依然有特殊含义,会被 Bash 自动扩展。

在双引号中,美元符号用来引用变量,反引号则是执行子命令,反斜杠则是用来转义,以反斜杠开头的不可打印字符则会失效。

{{CODE_BLOCK_6}}

通过回车插入的换行符在双引号之中,会失去特殊含义,Bash 正常情况下会将换行符解释为命令结束,但是换行符在双引号之中就失去了这种特殊作用,**只用来换行**,所以可以输入多行。`echo` 命令会将换行符原样输出,显示的时候正常解释为换行。所以可以利用双引号,在命令行输入多行文本。

{{CODE_BLOCK_7}}

但是你直接在双引号中手写 `\n` 是不行的

{{CODE_BLOCK_8}}

双引号的另一个常见的使用场合是,文件名包含空格。这时就必须使用双引号(或单引号),将文件名放在里面。否则 Bash 会将其理解为被被空格分割开的两个参数

双引号还有一个作用,就是保存原始命令的输出格式。

{{CODE_BLOCK_9}}

## Here 文档

Here 文档(here document)是一种输入多行字符串的方法,格式如下:

{{CODE_BLOCK_10}}

它的格式分成开始标记(`<< token`)和结束标记(`token`)。开始标记是两个小于号加上 token,中间可以有空格也可以没有空格,token 可以随意取,后面必须是一个换行符;结束标记是单独一行顶格写的 token,如果不是顶格,结束标记不起作用。两者之间就是多行字符串的内容。

> token 可以理解开始输入和结束输入的文本标记,阮一峰大佬说这是 Here 文档的名称,其实不合适

{{CODE_BLOCK_11}}

我们在 shell 脚本中创建文件并在其中填入内容的时候,经常使用 Here 文档。

{{CODE_BLOCK_12}}

在 Here 文档内部会发生变量解析,同时支持反斜杠转义,但是不支持通配符扩展,双引号和单引号也失去语法作用,变成了普通字符。

> 支持变量解析,让我们可以在脚本中根据变量动态地生成 Here 文档。

{{CODE_BLOCK_13}}

如果不希望发生变量替换,可以把 Here 文档的开始标记放在单引号之中。(结束标记不用放到单引号中)

Here 文档的本质是重定向,它将文档重定向给了某个命令的标准输入,所以,Here 文档只适合那些可以接受标准输入作为参数的命令,比如 `cat`、`grep`,有的命令不接受标准输入作为参数,比如 `echo`,所以 `echo` 命令无法配合 Here 文档。

> 关于标准输入跟命令行参数有什么区别,请看《Linux 文件系统基础》的 `| 管道符号` 小节

> 关于什么是重定向,请看《Linux 文件系统基础》的 `>指令和>>指令` 小节
> 
> 重定向和管道还是有区别的,阮一峰大佬的 [博客](https://wangdoc.com/bash/quotation#here-%E6%96%87%E6%A1%A3) 中写到重定向等同于管道的说法是错误的

此外,Here 文档也不能作为变量的值,只能用于命令的参数。

## Here 字符串

Here 文档还有一个变体,叫做 Here 字符串(Here string),使用三个小于号(`<<<`)表示。

{{CODE_BLOCK_14}}

它的作用是将字符串通过标准输入,传递给命令。

**有些命令直接接受给定的参数,与通过标准输入接受参数,结果是不一样的**。所以才有了这个语法,使得将字符串通过标准输入传递给命令更方便,比如 `cat` 命令只接受标准输入传入的字符串。

{{CODE_BLOCK_15}}

效果等同于 `echo hello world`

$
$ echo '$name'
$name
$ echo '*'
*
$ echo '$(ls)'
$(ls)
$ echo '$((2+2))'
$((2+2))
$ echo '\'
\

由于反斜杠在单引号里面变成了普通字符,所以如果单引号之中,还要使用单引号,不能使用转义,需要在外层的单引号前面加上一个美元符号($),然后再对里层的单引号转义。不过这种下,我们一般在双引号中使用单引号

{{CODE_BLOCK_5}}

双引号

双引号比单引号宽松,大部分特殊字符在双引号里面,都会失去特殊含义,变成普通字符,比如 *,这意味着,双引号里面不会进行文件名扩展。但是,三个特殊字符除外:美元符号($)、反引号(`)和反斜杠(\)。这三个字符在双引号之中,依然有特殊含义,会被 Bash 自动扩展。

在双引号中,美元符号用来引用变量,反引号则是执行子命令,反斜杠则是用来转义,以反斜杠开头的不可打印字符则会失效。

{{CODE_BLOCK_6}}

通过回车插入的换行符在双引号之中,会失去特殊含义,Bash 正常情况下会将换行符解释为命令结束,但是换行符在双引号之中就失去了这种特殊作用,只用来换行,所以可以输入多行。echo 命令会将换行符原样输出,显示的时候正常解释为换行。所以可以利用双引号,在命令行输入多行文本。

{{CODE_BLOCK_7}}

但是你直接在双引号中手写 \n 是不行的

{{CODE_BLOCK_8}}

双引号的另一个常见的使用场合是,文件名包含空格。这时就必须使用双引号(或单引号),将文件名放在里面。否则 Bash 会将其理解为被被空格分割开的两个参数

双引号还有一个作用,就是保存原始命令的输出格式。

{{CODE_BLOCK_9}}

Here 文档

Here 文档(here document)是一种输入多行字符串的方法,格式如下:

{{CODE_BLOCK_10}}

它的格式分成开始标记(<< token)和结束标记(token)。开始标记是两个小于号加上 token,中间可以有空格也可以没有空格,token 可以随意取,后面必须是一个换行符;结束标记是单独一行顶格写的 token,如果不是顶格,结束标记不起作用。两者之间就是多行字符串的内容。

token 可以理解开始输入和结束输入的文本标记,阮一峰大佬说这是 Here 文档的名称,其实不合适

{{CODE_BLOCK_11}}

我们在 shell 脚本中创建文件并在其中填入内容的时候,经常使用 Here 文档。

{{CODE_BLOCK_12}}

在 Here 文档内部会发生变量解析,同时支持反斜杠转义,但是不支持通配符扩展,双引号和单引号也失去语法作用,变成了普通字符。

支持变量解析,让我们可以在脚本中根据变量动态地生成 Here 文档。

{{CODE_BLOCK_13}}

如果不希望发生变量替换,可以把 Here 文档的开始标记放在单引号之中。(结束标记不用放到单引号中)

Here 文档的本质是重定向,它将文档重定向给了某个命令的标准输入,所以,Here 文档只适合那些可以接受标准输入作为参数的命令,比如 catgrep,有的命令不接受标准输入作为参数,比如 echo,所以 echo 命令无法配合 Here 文档。

关于标准输入跟命令行参数有什么区别,请看《Linux 文件系统基础》的 | 管道符号 小节

关于什么是重定向,请看《Linux 文件系统基础》的 >指令和>>指令 小节

重定向和管道还是有区别的,阮一峰大佬的 博客 中写到重定向等同于管道的说法是错误的

此外,Here 文档也不能作为变量的值,只能用于命令的参数。

Here 字符串

Here 文档还有一个变体,叫做 Here 字符串(Here string),使用三个小于号(<<<)表示。

{{CODE_BLOCK_14}}

它的作用是将字符串通过标准输入,传递给命令。

有些命令直接接受给定的参数,与通过标准输入接受参数,结果是不一样的。所以才有了这个语法,使得将字符串通过标准输入传递给命令更方便,比如 cat 命令只接受标准输入传入的字符串。

{{CODE_BLOCK_15}}

效果等同于 echo hello world
it's'
it's
$ echo "it's"
it's


## 双引号

双引号比单引号宽松,大部分特殊字符在双引号里面,都会失去特殊含义,变成普通字符,比如 `*`,这意味着,双引号里面不会进行文件名扩展。但是,三个特殊字符除外:美元符号(`$`)、反引号(`` ` ``)和反斜杠(`\`)。这三个字符在双引号之中,依然有特殊含义,会被 Bash 自动扩展。

在双引号中,美元符号用来引用变量,反引号则是执行子命令,反斜杠则是用来转义,以反斜杠开头的不可打印字符则会失效。

{{CODE_BLOCK_6}}

通过回车插入的换行符在双引号之中,会失去特殊含义,Bash 正常情况下会将换行符解释为命令结束,但是换行符在双引号之中就失去了这种特殊作用,**只用来换行**,所以可以输入多行。`echo` 命令会将换行符原样输出,显示的时候正常解释为换行。所以可以利用双引号,在命令行输入多行文本。

{{CODE_BLOCK_7}}

但是你直接在双引号中手写 `\n` 是不行的

{{CODE_BLOCK_8}}

双引号的另一个常见的使用场合是,文件名包含空格。这时就必须使用双引号(或单引号),将文件名放在里面。否则 Bash 会将其理解为被被空格分割开的两个参数

双引号还有一个作用,就是保存原始命令的输出格式。

{{CODE_BLOCK_9}}

## Here 文档

Here 文档(here document)是一种输入多行字符串的方法,格式如下:

{{CODE_BLOCK_10}}

它的格式分成开始标记(`<< token`)和结束标记(`token`)。开始标记是两个小于号加上 token,中间可以有空格也可以没有空格,token 可以随意取,后面必须是一个换行符;结束标记是单独一行顶格写的 token,如果不是顶格,结束标记不起作用。两者之间就是多行字符串的内容。

> token 可以理解开始输入和结束输入的文本标记,阮一峰大佬说这是 Here 文档的名称,其实不合适

{{CODE_BLOCK_11}}

我们在 shell 脚本中创建文件并在其中填入内容的时候,经常使用 Here 文档。

{{CODE_BLOCK_12}}

在 Here 文档内部会发生变量解析,同时支持反斜杠转义,但是不支持通配符扩展,双引号和单引号也失去语法作用,变成了普通字符。

> 支持变量解析,让我们可以在脚本中根据变量动态地生成 Here 文档。

{{CODE_BLOCK_13}}

如果不希望发生变量替换,可以把 Here 文档的开始标记放在单引号之中。(结束标记不用放到单引号中)

Here 文档的本质是重定向,它将文档重定向给了某个命令的标准输入,所以,Here 文档只适合那些可以接受标准输入作为参数的命令,比如 `cat`、`grep`,有的命令不接受标准输入作为参数,比如 `echo`,所以 `echo` 命令无法配合 Here 文档。

> 关于标准输入跟命令行参数有什么区别,请看《Linux 文件系统基础》的 `| 管道符号` 小节

> 关于什么是重定向,请看《Linux 文件系统基础》的 `>指令和>>指令` 小节
> 
> 重定向和管道还是有区别的,阮一峰大佬的 [博客](https://wangdoc.com/bash/quotation#here-%E6%96%87%E6%A1%A3) 中写到重定向等同于管道的说法是错误的

此外,Here 文档也不能作为变量的值,只能用于命令的参数。

## Here 字符串

Here 文档还有一个变体,叫做 Here 字符串(Here string),使用三个小于号(`<<<`)表示。

{{CODE_BLOCK_14}}

它的作用是将字符串通过标准输入,传递给命令。

**有些命令直接接受给定的参数,与通过标准输入接受参数,结果是不一样的**。所以才有了这个语法,使得将字符串通过标准输入传递给命令更方便,比如 `cat` 命令只接受标准输入传入的字符串。

{{CODE_BLOCK_15}}

效果等同于 `echo hello world`

$
$ echo '$name'
$name
$ echo '*'
*
$ echo '$(ls)'
$(ls)
$ echo '$((2+2))'
$((2+2))
$ echo '\'
\

由于反斜杠在单引号里面变成了普通字符,所以如果单引号之中,还要使用单引号,不能使用转义,需要在外层的单引号前面加上一个美元符号($),然后再对里层的单引号转义。不过这种下,我们一般在双引号中使用单引号

{{CODE_BLOCK_5}}

双引号

双引号比单引号宽松,大部分特殊字符在双引号里面,都会失去特殊含义,变成普通字符,比如 *,这意味着,双引号里面不会进行文件名扩展。但是,三个特殊字符除外:美元符号($)、反引号(`)和反斜杠(\)。这三个字符在双引号之中,依然有特殊含义,会被 Bash 自动扩展。

在双引号中,美元符号用来引用变量,反引号则是执行子命令,反斜杠则是用来转义,以反斜杠开头的不可打印字符则会失效。

{{CODE_BLOCK_6}}

通过回车插入的换行符在双引号之中,会失去特殊含义,Bash 正常情况下会将换行符解释为命令结束,但是换行符在双引号之中就失去了这种特殊作用,只用来换行,所以可以输入多行。echo 命令会将换行符原样输出,显示的时候正常解释为换行。所以可以利用双引号,在命令行输入多行文本。

{{CODE_BLOCK_7}}

但是你直接在双引号中手写 \n 是不行的

{{CODE_BLOCK_8}}

双引号的另一个常见的使用场合是,文件名包含空格。这时就必须使用双引号(或单引号),将文件名放在里面。否则 Bash 会将其理解为被被空格分割开的两个参数

双引号还有一个作用,就是保存原始命令的输出格式。

{{CODE_BLOCK_9}}

Here 文档

Here 文档(here document)是一种输入多行字符串的方法,格式如下:

{{CODE_BLOCK_10}}

它的格式分成开始标记(<< token)和结束标记(token)。开始标记是两个小于号加上 token,中间可以有空格也可以没有空格,token 可以随意取,后面必须是一个换行符;结束标记是单独一行顶格写的 token,如果不是顶格,结束标记不起作用。两者之间就是多行字符串的内容。

token 可以理解开始输入和结束输入的文本标记,阮一峰大佬说这是 Here 文档的名称,其实不合适

{{CODE_BLOCK_11}}

我们在 shell 脚本中创建文件并在其中填入内容的时候,经常使用 Here 文档。

{{CODE_BLOCK_12}}

在 Here 文档内部会发生变量解析,同时支持反斜杠转义,但是不支持通配符扩展,双引号和单引号也失去语法作用,变成了普通字符。

支持变量解析,让我们可以在脚本中根据变量动态地生成 Here 文档。

{{CODE_BLOCK_13}}

如果不希望发生变量替换,可以把 Here 文档的开始标记放在单引号之中。(结束标记不用放到单引号中)

Here 文档的本质是重定向,它将文档重定向给了某个命令的标准输入,所以,Here 文档只适合那些可以接受标准输入作为参数的命令,比如 catgrep,有的命令不接受标准输入作为参数,比如 echo,所以 echo 命令无法配合 Here 文档。

关于标准输入跟命令行参数有什么区别,请看《Linux 文件系统基础》的 | 管道符号 小节

关于什么是重定向,请看《Linux 文件系统基础》的 >指令和>>指令 小节

重定向和管道还是有区别的,阮一峰大佬的 博客 中写到重定向等同于管道的说法是错误的

此外,Here 文档也不能作为变量的值,只能用于命令的参数。

Here 字符串

Here 文档还有一个变体,叫做 Here 字符串(Here string),使用三个小于号(<<<)表示。

{{CODE_BLOCK_14}}

它的作用是将字符串通过标准输入,传递给命令。

有些命令直接接受给定的参数,与通过标准输入接受参数,结果是不一样的。所以才有了这个语法,使得将字符串通过标准输入传递给命令更方便,比如 cat 命令只接受标准输入传入的字符串。

{{CODE_BLOCK_15}}

效果等同于 echo hello world