前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >heredoc细节妙用

heredoc细节妙用

作者头像
PedroQin
发布2019-12-18 11:23:35
6200
发布2019-12-18 11:23:35
举报
文章被收录于专栏:WriteSimpleDemoWriteSimpleDemo

Here文档

here文档,又称作heredochereishere-字串here-脚本,是一种在命令行shell(如sh、csh、ksh、bash、PowerShell和zsh)和程序语言(像Perl、PHP、Python和Ruby)里定义一个字串的方法。它可以保存文字里面的换行或是缩排等空白字元。一些语言允许在字串里执行变量替换和命令替换。 here文档最通用的语法是 <<紧跟一个标识符,从下一行开始是想要引用的文字,然后再在单独的一行用相同的标识符关闭。在Unix shell里,here文档通常用于给命令提供输入内容。

shell

在以下几个例子中,文字用here文档传递给 tr命令。

代码语言:javascript
复制
$ 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 THREE和 UNO DOS TRES是执行后 tr的输出。

在<<后面添加一个减号,可以使TAB字元被忽略。这允许在shell脚本中缩进here文档而不改变它们的值。(注意在命令行上可能会需要输入 Ctrl-v TAB来真正地输入一个制表符。下边的例子用空格模拟制表符;不要复制粘贴。)

代码语言:javascript
复制
$ tr a-z A-Z <<-END_TEXT
 >         one two three
 >         uno dos tres
 > END_TEXT
 ONE TWO THREE
 UNO DOS TRES

默认地,会进行变量替换和命令替换:

代码语言:javascript
复制
$ cat << EOF
 > Working dir $PWD
 > EOF
 Working dir /home/user

这可以通过使用引号包裹标识符来禁用。可以使用单引号或双引号

代码语言:javascript
复制
$ cat << "EOF"
 > Working dir $PWD
 > EOF
 Working dir $PWD

bash,ksh或zsh中也可以用here-字串:

代码语言:javascript
复制
$ tr a-z A-Z <<<"Yes it is a string"
 YES IT IS A STRING

进阶使用

初始

代码:

代码语言:javascript
复制
#!/bin/bash

cat <<blocks
 .----------------.
| .--------------. |
| |      __      | |
| |     /  \     | |
| |    / /\ \    | |
| |   / ____ \   | |
| | _/ /    \ \_ | |
| ||____|  |____|| |
| |              | |
| '--------------' |
 '----------------'
blocks

执行没有问题:

代码语言:javascript
复制
apple@Pedro-Mac-mini ~/D/O/O/linux> bash ascii_signature.sh
 .----------------.
| .--------------. |
| |      __      | |
| |     /  \     | |
| |    / /\ \    | |
| |   / ____ \   | |
| | _/ /    \ \_ | |
| ||____|  |____|| |
| |              | |
| '--------------' |
 '----------------' 
apple@Pedro-Mac-mini ~/D/O/O/linux>
加了特殊字符“`”之后

代码:

代码语言:javascript
复制
#!/bin/bash

cat <<blocks
 .----------------. `
| .--------------. |
| |      __      | |
| |     /  \     | |
| |    / /\ \    | |
| |   / ____ \   | |
| | _/ /    \ \_ | |
| ||____|  |____|| |
| |              | |
| '--------------' |
 '----------------'
blocks

执行时有错误:

代码语言:javascript
复制
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>
将开头的delimiter引号引起来

代码:

代码语言:javascript
复制
#!/bin/bash

cat <<"blocks"
 .----------------. `
| .--------------. |
| |      __      | |
| |     /  \     | |
| |    / /\ \    | |
| |   / ____ \   | |
| | _/ /    \ \_ | |
| ||____|  |____|| |
| |              | |
| '--------------' |
 '----------------'
blocks

执行成功:

代码语言:javascript
复制
apple@Pedro-Mac-mini ~/D/O/O/linux> bash ascii_signature.sh
 .----------------. `
| .--------------. |
| |      __      | |
| |     /  \     | |
| |    / /\ \    | |
| |   / ____ \   | |
| | _/ /    \ \_ | |
| ||____|  |____|| |
| |              | |
| '--------------' |
 '----------------'
apple@Pedro-Mac-mini ~/D/O/O/linux>
将其赋值给变量时

代码:

代码语言:javascript
复制
#!/bin/bash

export a=`cat <<"blocks"
 .----------------. `
| .--------------. |
| |      __      | |
| |     /  \     | |
| |    / /\ \    | |
| |   / ____ \   | |
| | _/ /    \ \_ | |
| ||____|  |____|| |
| |              | |
| '--------------' |
 '----------------'
blocks`

echo "$a"

执行出错:

代码语言:javascript
复制
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>
需使用eval

这种写法的目的是:隔离 heredoc 的语法解析细节就和外层的shell调用( ``或者$(..))。 这种写法为什么可以正确地工作?因为eval引入了一个子结构,这样 eval... 作为一个整体来接受输入,不管它是 heredoc 还是别的字串,比如也可以是一个文件重定向(eval 'var=`cat`' < file)。

代码语言:javascript
复制
#!/bin/bash

eval 'export a=`cat`' <<"blocks"
 .----------------. `
| .--------------. |
| |      __      | |
| |     /  \     | |
| |    / /\ \    | |
| |   / ____ \   | |
| | _/ /    \ \_ | |
| ||____|  |____|| |
| |              | |
| '--------------' |
 '----------------'
blocks

echo "$a"

运行结果:

代码语言:javascript
复制
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>

甚至你还可以像这样:

代码语言:javascript
复制
#!/bin/bash

eval 'export a=`cat`' <<"blocks"
 .----------------. `
| .--------------. |
| |      __      | |
| |     /  \     | |
| |    / /\ \    | |
| |   / ____ \   | |
| | _/ /    \ \_ | |
| ||____|  |____|| |
| |              | |
| '--------------' |
 '----------------'

b=`cat <<"block_B"
 .----------------.
| .--------------. |
| |   ______     | |
| |  |_   _ \    | |
| |    | |_) |   | |
| |    |  __'.   | |
| |   _| |__) |  | |
| |  |_______/   | |
| |              | |
| '--------------' |
 '----------------'
block_B`
blocks

echo "$a"

执行结果:

代码语言:javascript
复制
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)

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-12-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 WriteSimpleDemo 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Here文档
  • shell
  • 进阶使用
    • 初始
      • 加了特殊字符“`”之后
        • 将开头的delimiter引号引起来
          • 将其赋值给变量时
            • 需使用eval
            • 参考文档
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档