shell重定向之Here Documents和Here Strings

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.

从输出可以看出以下几点

  1. 输出中包含了缩进。如果有多行格式化的文本需要输出,相比使用 echo 命令,here documents 显示简洁很多。
  2. 参数展开($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

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
shell 脚本中,`=`、`==` 和 `=~` 都是用于字符串比较的符号,它们的区别如下: 1. `=` 用于测试两个字符串是否相等。它可以用于 `[]` 和 `[[ ]]` 中。 举个例子,如果我们要测试一个字符串是否等于另一个字符串,可以使用 `=`: ``` if [ "$string1" = "$string2" ]; then echo "The two strings are equal." fi ``` 这个例子中,`[ "$string1" = "$string2" ]` 表示测试 `$string1` 是否等于 `$string2`。如果条件为真,则执行 `echo` 命令输出一条消息。 需要注意的是,`=` 左右两侧的字符串需要用双引号括起来,以避免被 shell 解释成其他含义。 2. `==` 也用于测试两个字符串是否相等,它可以用于 `[]` 和 `[[ ]]` 中。`==` 与 `=` 的作用相同,只是语法略有不同。在 `[]` 中,`==` 可以用单引号括起来,但是在 `[[ ]]` 中不能用单引号括起来。 举个例子,如果我们要测试一个字符串是否等于另一个字符串,可以使用 `==`: ``` if [ "$string1" == "$string2" ]; then echo "The two strings are equal." fi ``` 这个例子中,`[ "$string1" == "$string2" ]` 表示测试 `$string1` 是否等于 `$string2`。如果条件为真,则执行 `echo` 命令输出一条消息。 需要注意的是,`==` 左右两侧的字符串需要用双引号括起来,以避免被 shell 解释成其他含义。 3. `=~` 用于测试一个字符串是否匹配某个正则表达式。它只能用于 `[[ ]]` 中。 举个例子,如果我们要测试一个字符串是否匹配某个正则表达式,可以使用 `=~`: ``` if [[ "$string" =~ ^prefix.*$ ]]; then echo "The string matches the pattern." fi ``` 这个例子中,`[[ "$string" =~ ^prefix.*$ ]]` 表示测试 `$string` 是否匹配正则表达式 `^prefix.*$`。如果条件为真,则执行 `echo` 命令输出一条消息。 需要注意的是,`=~` 左侧的字符串需要用双引号括起来,而且正则表达式不需要用引号括起来。但是,如果正则表达式中包含空格、通配符或变量,建议使用引号括起来。 综上所述,`=`、`==` 和 `=~` 都是用于字符串比较的符号,但是 `=` 和 `==` 用于测试相等,而 `=~` 用于测试正则表达式匹配。另外,`=` 和 `==` 可以用于 `[]` 和 `[[ ]]` 中,而 `=~` 只能用于 `[[ ]]` 中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值