Here Documents
语法
[n]<<[-]word
here-document
delimiter
如果省略n,那么 Here Documents 会把 here-document 读入到命令的标准输入中,否则读入到文件描述符 n 中。
delimiter 后面不能包括空空格或制表符
如果 word 不加引号,那么 delimiter 值与 word 值一样,并且 here document 中可以支持参数展开,命令替换,以及算法表达式展开。
#!/bin/bash
NAME=David
cat << _EOF_
Hello Brown:
I'm $NAME, today is $(date), and I have played $((1+1)) games.
_EOF_
执行这个脚本,输出如下
Hello Brown:
I'm David, today is 2020年 09月 25日 星期五 16:37:34 CST, and I have played 2 games.
从输出可以看出以下几点
- 输出中包含了缩进。如果有多行格式化的文本需要输出,相比使用 echo 命令,here documents 显示简洁很多。
- 参数展开(
$NAME
),命令替换($(date)
),算法表达式展开($((1+1))
)可以被正确执行。
现在来另外一种情况,如果语法中的 word 加引号,那么 delimiter 就是 word 去引号的值,并且 here-document 中的行不支持任何 shell 展开。
#!/bin/bash
NAME=David
cat << "_EOF_"
Hello Brown:
I'm $NAME, today is $(date), and I have played $((1+1)) games.
_EOF_
输出结果为
Hello Brown:
I'm $NAME, today is $(date), and I have played $((1+1)) games.
从输出可以看到,如果语法中的 word 加了引号,here-document 中的行不支持 shell 展开。
上面的例子,都是在行首使用 here documents 语法,但是有时候为了保持缩进,不会在行首使用 here document 语法,这就使语法中的 delimiter 前面包含了空白字符(空格,或者制表符),这样程序是无法执行的,如下
#!/bin/bash
function hello()
{
cat << _EOF_
hello world!
_EOF_
}
# 执行hello函数
hello
为了保持漂亮的缩进,在 hello 函数添加了带有缩进的 here documents 语法,如果你的编辑器开启了语法高亮,应该会提示你语法错误。这是因为最后一个 _EOF_
前面有空格或制表符。当然我们可以把前面的空格和制表符删除来解决问题,这是最直观的解决办法,但是这影响代码漂亮的缩进。
但是还有一种办法,那就是把语法中的<<
改为<<-
,这样就可以在 delimiter 前使用制表符,但是不能使用空格。并且内容行前面的制表符将被忽略,但是空格不会被忽略。
#!/bin/bash
function hello()
{
cat <<- _EOF_
hello world!
_EOF_
}
hello
很多编辑器会把 tab 展开为空格,因为高级语言,例如c, c++, java,都是习惯用空格代替制表符,因此当你使用tab时,会插入4个空格。如果是这样的情况,那么你永远不能在 shell 脚本中插入制表符。如果你使用 vim 编写 shell 脚本,可以参考我的文章 vim中令人头疼的缩进该怎么配置,教你如果在 vim 中配置缩进,以便正确写 shell 脚本。
另外,如果使用 Here Documents 语法把内容输出到一个文件中,语法如下
[n] << [-]word > file
here-document
delimiter
就是在 word 后面进行重定向即可,例子就不演示了。
Here Strings
Here Strings 是 Here Documents 的一种变体,语法如下
[n] <<< word
注意,Here Documents 使用两个小于号,而 Here Strings 使用三个小于号。
Here Strings 语法是把 word 以一个单一字符串并加上换行符,发送到命令的标准输入或者文件描述符n中。
#!/bin/bash
cat <<< "hello world"
就是这么简单,没有什么其实需要注意的。
在 The Linux Command Line 一书中,有一个使用 Here Strings 非常棒的例子,可以参考学习下。
参考
GNU Bash Reference Manual 中关于 Here Documents
https://www.gnu.org/software/bash/manual/bash.html#Here-Documents