专栏首页WriteSimpleDemoheredoc细节妙用

heredoc细节妙用

Here文档

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

shell

在以下几个例子中,文字用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 THREE和 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>

将开头的delimiter引号引起来

代码:

#!/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>

需使用eval

这种写法的目的是:隔离 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(this_is_a_wechat),作者:PedroQin

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-12-12

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • linux ${}表达式详解

    $(var:-default) 当var为空或未定义时整个表达式的值为default

    PedroQin
  • Shell 脚本实现串口操作

    实际生产测试需求中,常常有串口连通性测试,其对应的最简单的测试方法即:「调用非交互式串口工具登录串口并发送(命令)接收数据(命令返回)」。

    PedroQin
  • 基于树莓派的多功能USB实现--U盘模式和网卡模式

    一般来说,USB 设备有两种,一种是 Host,比如电脑,可以去读取其他 USB 设备的数据,另外一种是 Device,比如键盘鼠标U盘智能手机。而OTG(文末...

    PedroQin
  • linux删除环境变量步骤详解

    砸漏
  • 给你一个完整高效的linux系统

    章鱼喵
  • 深入浅出——搞懂卷积神经网络误差分析(一)

    第一部分 全连接网络的权值更新   卷积神经网络使用基于梯度的学习方法进行监督训练,实践中,一般使用随机梯度下降(机器学习中几种常见的梯度下降方式)的版本,对于...

    深度学习思考者
  • CNN入门再介绍

    导语:学习深度神经网络方面的算法已经有一段时间了,对目前比较经典的模型也有了一些了解。这种曾经一度低迷的方法现在已经吸引了很多领域的目光,在几年前仅仅存在于研究...

    IT派
  • 深度学习入门:几幅手稿讲解CNN

    作者:岳翰 电子科技大学|数学科学学院 来源自 JohnHany的博客 量子位 已获授权编辑发布 学习深度神经网络方面的算法已经有一段时间了,对目前比较经典的模...

    量子位
  • 花马云10亿无作为,被同事骂的当众落泪,后为阿里创造4500亿价值

    后来,他成为阿里巴巴集团首席技术官,而且被公认为,近10年来,中国最好的首席技术官。

    良月柒
  • OS X开发NSMenu应用详解 原

        NSMenu在Mac桌面软件开发中往往有3个方面的应用,作为程序的主菜单栏使用,作为视图邮件菜单使用和作为Dock菜单使用。

    珲少

扫码关注云+社区

领取腾讯云代金券