here文档,又称作heredoc、hereis、here-字串或here-脚本,是一种在命令行shell(如sh、csh、ksh、bash、PowerShell和zsh)和程序语言(像Perl、PHP、Python和Ruby)里定义一个字串的方法。它可以保存文字里面的换行或是缩排等空白字元。一些语言允许在字串里执行变量替换和命令替换。 here文档最通用的语法是
<<
紧跟一个标识符,从下一行开始是想要引用的文字,然后再在单独的一行用相同的标识符关闭。在Unix shell里,here文档通常用于给命令提供输入内容。
在以下几个例子中,文字用here文档传递给 tr
命令。
$ tr a-z A-Z <<END_TEXT
> one two three
> uno dos tres
> END_TEXT
ONE TWO THREE
UNO DOS TRES
END_TEXT
被用作标识符。它指定了here文档的开始和结束 ONE TWO THRE
E和 UNO DOS TRES
是执行后 tr
的输出。
在<<后面添加一个减号,可以使TAB字元被忽略。这允许在shell脚本中缩进here文档而不改变它们的值。(注意在命令行上可能会需要输入 Ctrl-v TAB
来真正地输入一个制表符。下边的例子用空格模拟制表符;不要复制粘贴。)
$ tr a-z A-Z <<-END_TEXT
> one two three
> uno dos tres
> END_TEXT
ONE TWO THREE
UNO DOS TRES
默认地,会进行变量替换和命令替换:
$ cat << EOF
> Working dir $PWD
> EOF
Working dir /home/user
这可以通过使用引号包裹标识符来禁用。可以使用单引号或双引号:
$ cat << "EOF"
> Working dir $PWD
> EOF
Working dir $PWD
bash,ksh或zsh中也可以用here-字串:
$ tr a-z A-Z <<<"Yes it is a string"
YES IT IS A STRING
代码:
#!/bin/bash
cat <<blocks
.----------------.
| .--------------. |
| | __ | |
| | / \ | |
| | / /\ \ | |
| | / ____ \ | |
| | _/ / \ \_ | |
| ||____| |____|| |
| | | |
| '--------------' |
'----------------'
blocks
执行没有问题:
apple@Pedro-Mac-mini ~/D/O/O/linux> bash ascii_signature.sh
.----------------.
| .--------------. |
| | __ | |
| | / \ | |
| | / /\ \ | |
| | / ____ \ | |
| | _/ / \ \_ | |
| ||____| |____|| |
| | | |
| '--------------' |
'----------------'
apple@Pedro-Mac-mini ~/D/O/O/linux>
代码:
#!/bin/bash
cat <<blocks
.----------------. `
| .--------------. |
| | __ | |
| | / \ | |
| | / /\ \ | |
| | / ____ \ | |
| | _/ / \ \_ | |
| ||____| |____|| |
| | | |
| '--------------' |
'----------------'
blocks
执行时有错误:
apple@Pedro-Mac-mini ~/D/O/O/linux> bash ascii_signature.sh
ascii_signature.sh: line 3: bad substitution: no closing "`" in `
| .--------------. |
| | __ | |
| | / \ | |
| | / /\ \ | |
| | / ____ \ | |
| | _/ / \ \_ | |
| ||____| |____|| |
| | | |
| '--------------' |
'----------------'
apple@Pedro-Mac-mini ~/D/O/O/linux>
代码:
#!/bin/bash
cat <<"blocks"
.----------------. `
| .--------------. |
| | __ | |
| | / \ | |
| | / /\ \ | |
| | / ____ \ | |
| | _/ / \ \_ | |
| ||____| |____|| |
| | | |
| '--------------' |
'----------------'
blocks
执行成功:
apple@Pedro-Mac-mini ~/D/O/O/linux> bash ascii_signature.sh
.----------------. `
| .--------------. |
| | __ | |
| | / \ | |
| | / /\ \ | |
| | / ____ \ | |
| | _/ / \ \_ | |
| ||____| |____|| |
| | | |
| '--------------' |
'----------------'
apple@Pedro-Mac-mini ~/D/O/O/linux>
代码:
#!/bin/bash
export a=`cat <<"blocks"
.----------------. `
| .--------------. |
| | __ | |
| | / \ | |
| | / /\ \ | |
| | / ____ \ | |
| | _/ / \ \_ | |
| ||____| |____|| |
| | | |
| '--------------' |
'----------------'
blocks`
echo "$a"
执行出错:
apple@Pedro-Mac-mini ~/D/O/O/linux> bash ascii_signature.sh
ascii_signature.sh: line 5: syntax error near unexpected token `|'
ascii_signature.sh: line 5: `| .--------------. |'
apple@Pedro-Mac-mini ~/D/O/O/linux>
这种写法的目的是:隔离 heredoc 的语法解析细节就和外层的shell调用(
``
或者$(..)
)。 这种写法为什么可以正确地工作?因为eval引入了一个子结构,这样eval...
作为一个整体来接受输入,不管它是 heredoc 还是别的字串,比如也可以是一个文件重定向(eval 'var=`cat`' < file)。
#!/bin/bash
eval 'export a=`cat`' <<"blocks"
.----------------. `
| .--------------. |
| | __ | |
| | / \ | |
| | / /\ \ | |
| | / ____ \ | |
| | _/ / \ \_ | |
| ||____| |____|| |
| | | |
| '--------------' |
'----------------'
blocks
echo "$a"
运行结果:
apple@Pedro-Mac-mini ~/D/O/O/linux> bash ascii_signature.sh
.----------------. `
| .--------------. |
| | __ | |
| | / \ | |
| | / /\ \ | |
| | / ____ \ | |
| | _/ / \ \_ | |
| ||____| |____|| |
| | | |
| '--------------' |
'----------------'
apple@Pedro-Mac-mini ~/D/O/O/linux> . ./ascii_signature.sh
.----------------. `
| .--------------. |
| | __ | |
| | / \ | |
| | / /\ \ | |
| | / ____ \ | |
| | _/ / \ \_ | |
| ||____| |____|| |
| | | |
| '--------------' |
'----------------'
apple@Pedro-Mac-mini ~/D/O/O/linux> echo "$a"
.----------------. `
| .--------------. |
| | __ | |
| | / \ | |
| | / /\ \ | |
| | / ____ \ | |
| | _/ / \ \_ | |
| ||____| |____|| |
| | | |
| '--------------' |
'----------------'
apple@Pedro-Mac-mini ~/D/O/O/linux>
甚至你还可以像这样:
#!/bin/bash
eval 'export a=`cat`' <<"blocks"
.----------------. `
| .--------------. |
| | __ | |
| | / \ | |
| | / /\ \ | |
| | / ____ \ | |
| | _/ / \ \_ | |
| ||____| |____|| |
| | | |
| '--------------' |
'----------------'
b=`cat <<"block_B"
.----------------.
| .--------------. |
| | ______ | |
| | |_ _ \ | |
| | | |_) | | |
| | | __'. | |
| | _| |__) | | |
| | |_______/ | |
| | | |
| '--------------' |
'----------------'
block_B`
blocks
echo "$a"
执行结果:
apple@Pedro-Mac-mini ~/D/O/O/linux> bash ascii_signature.sh
.----------------. `
| .--------------. |
| | __ | |
| | / \ | |
| | / /\ \ | |
| | / ____ \ | |
| | _/ / \ \_ | |
| ||____| |____|| |
| | | |
| '--------------' |
'----------------'
b=`cat <<"block_B"
.----------------.
| .--------------. |
| | ______ | |
| | |_ _ \ | |
| | | |_) | | |
| | | __'. | |
| | _| |__) | | |
| | |_______/ | |
| | | |
| '--------------' |
'----------------'
block_B`
apple@Pedro-Mac-mini ~/D/O/O/linux>
Here文档(https://zh.wikipedia.org/wiki/Here%E6%96%87%E6%A1%A3)
本文分享自 WriteSimpleDemo 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体分享计划 ,欢迎热爱写作的你一起参与!