如何在 Linux 上的 Bash 中使用“这里的文档”

已发表: 2022-01-29
Linux 计算机系统上的终端窗口。
Fatmawati Achmad Zaenuri/Shutterstock

奇怪的命名为“here documents”让您可以在 Linux 上的 Bash 脚本中使用输入/输出重定向。 它们是自动化您需要在远程计算机上运行的命令的好方法。

这里的文件

Linux 中的许多命令都有两个或三个字母的名称。 这在一定程度上引起了人们认为 Linux 难以学习且充满神秘命令的概念。 但是 Linux 中最奇怪的名字之一并不是神秘短的名字之一。 “这里的文档”不是文档,“这里”指的是什么也不是很清楚。

它们是一个相对晦涩的构造,但它们很有用。 当然,这是 Linux,所以给猫剥皮的方法不止一种。 此处文档提供的某些功能可以通过其他方式复制。 这些替代方法通常更复杂。 在编程和脚本中,“更复杂”也意味着“更容易出现错误”,并且您的代码更难维护。

此处文档真正出色的地方在于,您希望从脚本中建立的连接发送到远程计算机的命令的自动化。 建立连接很容易,但是一旦建立连接,如何将脚本中的命令“泵”到远程计算机的 shell 中? 这里的文档可以让您非常简单地做到这一点。

Here文档的基本原理

此处文档的惯用表示如下所示:

 命令 << 限制字符串
 .
 .
文本 
数据
变量
.
.
限制字符串
  • COMMAND :这可以是任何接受重定向输入的 Linux 命令。 请注意, echo命令不接受重定向输入。 如果您需要写入屏幕,可以使用cat命令。
  • << :重定向运算符。
  • limit_string :这是一个标签。 只要它没有出现在您重定向到命令中的数据列表中,它就可以是您喜欢的任何东西。 它用于标记文本、数据和变量列表的结束。
  • 数据列表:要提供给命令的数据列表。 它可以包含命令、文本和变量。 数据列表的内容一次一行地输入到命令中,直到遇到 _limit_string。
广告

您可能会在此处看到使用“EOF”作为限制字符串的文档示例。 我们不赞成这种做法。 它有效,但“EOF”表示“文件结束”。 除了家庭文档是脚本文件中最后一件事的罕见情况外,“EOF”被错误地使用。

如果您使用引用您正在做的事情的限制字符串,它将使您的脚本更具可读性。 如果您通过安全外壳 (SSH) 向远程计算机发送一系列命令,那么一个名为“_remote_commands”之类的限制字符串将非常有意义。 您不需要以下划线“ _ ”字符开头。 我们这样做是因为它在您的脚本中将它们标记为与众不同的东西。

简单的例子

您可以在命令行和脚本中使用此处的文档。 当您在终端窗口中键入以下内容时,每次按“Enter”时都会看到“ > ”行继续提示。 当您键入“_end_of_text”限制字符串并按“Enter”时,网站列表将传递给cat,并显示在终端窗口中。

 猫 << _end_of_text 
极客指南 
评论极客 
生活精明 
精通云的 IT
心灵反弹
_end_of_text 

这不是最有价值的练习,但它确实表明在整理整个数据列表并遇到限制字符串之前,不会向命令发送任何内容。 在您输入限制字符串“_end_of_text”并按“Enter”键之前, cat命令不会接收任何输入。

我们可以在脚本中做同样的事情。 将此示例键入或复制到编辑器中,将文件另存为“heredoc-1.sh”,然后关闭编辑器。

 #!/bin/bash

猫 << "_end_of_text"
您的用户名是:$(whoami)
您当前的工作目录是:$PWD
你的 Bash 版本是:$BASH_VERSION
_end_of_text

当您阅读本文时,每次创建脚本时,您都需要使其可执行,然后才能运行。 在每种情况下,使用chmod命令。 将每个示例中的脚本名称替换为此处使用的脚本名称。

 chmod +x heredoc-1.sh 

广告

该脚本包含两个环境变量$PWD$BASH_VERSION 。 执行脚本时,环境变量名称被它们的数据值(当前工作目录和 Bash 版本)替换。

该脚本还对whoami命令使用命令替换。 命令的名称被其自己的输出替换。 整个脚本的输出由 cat 命令写入终端窗口。 我们通过名称调用它来运行脚本:

 ./heredoc-1.sh 

如果修改脚本,将 here 文档第一行的限制字符串用引号“ " ”括起来,则数据列表将逐字传递给 here 文档命令。显示变量名称而不是变量值,命令替换将不发生。

 #!/bin/bash

猫<<-“_end_of_text”
您的用户名是:$(whoami)
您当前的工作目录是:$PWD
你的 Bash 版本是:$BASH_VERSION
_end_of_text
 ./heredoc-1.sh 

处理制表符

默认情况下,数据列表中的制表符将被保留并写入终端窗口。 复制此示例并将其另存为“heredoc-2.sh”。 使用chmod命令使其可执行。 编辑缩进的行以确保它们在行首有一个或两个制表符而不是一系列空格。

 #!/bin/bash

猫 << _end_of_text
您的用户名是:$(whoami)
  您当前的工作目录是:$PWD
    你的 Bash 版本是:$BASH_VERSION
_end_of_text
 ./heredoc-2.sh 

选项卡被写入终端窗口。

通过向重定向运算符添加破折号“ - ”,此处的文档将忽略前导制表符。 将此示例保存为“heredoc-3.sh”并使其可执行。

 #!/bin/bash

猫 <<- _end_of_text
您的用户名是:$(whoami)
  您当前的工作目录是:$PWD
    你的 Bash 版本是:$BASH_VERSION
_end_of_text
 ./heredoc-3.sh 

选项卡被忽略。 这可能看起来微不足道,但由于脚本的缩进部分,它是处理前导选项卡的一种巧妙方法。

广告

循环和其他逻辑结构通常是缩进的。 如果您的 here 文档包含在脚本的缩进部分中,则在重定向运算符中使用破折号“ - ”可以消除由前导制表符引起的格式问题。

 #!/bin/bash

如果是真的; 然后
  猫 <<- _limit_string
  第 1 行带有前导制表符。
  第 2 行带有前导制表符。
  第 3 行带有前导制表符。
  _limit_string
菲

重定向到文件

与 here 文档一起使用的命令的输出可以重定向到文件中。 在此处文档的第一行中的限制字符串之后使用“ > ”(创建文件)或“ >> ”(如果文件不存在则创建文件,如果存在则附加到文件)重定向运算符。

这个脚本是“heredoc-4.sh”。 它将其输出重定向到一个名为“session.txt”的文本文件。

 #!/bin/bash

猫 << _end_of_text > session.txt
您的用户名是:$(whoami)
您当前的工作目录是:$PWD
你的 Bash 版本是:$BASH_VERSION
_end_of_text
 ./heredoc-4.sh
 猫会话.text 

将输出传送到另一个命令

此处文档中使用的命令的输出可以通过管道作为另一个命令的输入。 使用管道“ | ” 运算符位于此处文档第一行中的限制字符串之后。 我们将把 here document 命令cat的输出通过管道传输到sed中。 我们想用字母“e”替换所有出现的字母“a”。

将此脚本命名为“heredoc-5.sh”。

 #!/bin/bash

猫 << _end_of_text | sed 's/a/e/g'
如何
到
盖克
_end_of_text
 ./heredoc-5.sh

“Gaak”被更正为“Geek”。

向函数发送参数

与此处文档一起使用的命令可以是脚本中的函数。

此脚本将一些车辆数据传递到函数中。 该函数读取数据,就好像它是由用户输入的一样。 然后打印变量的值。 将此脚本另存为“heredoc-6.sh”。

 #!/bin/bash

# set_car_details() 函数
set_car_details ()
{
读作
读取模型
阅读 new_used
阅读delivery_collect
读取位置
阅读价格
}

# 将数据传递给 set_car_details() 的 here 文档
set_car_details << _mars_rover_data
美国国家航空航天局
毅力漫游者
用过的
搜集
火星(经纬度)77.451865,18.445161
22亿
_mars_rover_data

# 获取车辆详细信息
回声“制作:$make”
回声“模型:$模型”
echo "新的或二手的:$new_used"
echo "送货或收货:$delivery_collect"
回声“位置:$位置”
回声“价格\$:$价格”
 ./heredoc-6.sh 

车辆详细信息被写入终端窗口。

创建和发送电子邮件

我们可以使用此处的文档来撰写和发送电子邮件。 注意,我们可以在重定向操作符前面给命令传递参数。 我们使用Linux mail命令通过本地邮件系统向名为“dave”的用户帐户发送电子邮件。 -s (主题)选项允许我们指定电子邮件的主题。

此示例形成脚本“heredoc-7.sh”。

 #!/bin/bash

article="这里文档"

mail -s '工作负载状态' dave << _project_report
用户名:$(whoami)
已完成任务:
文章:$article
_项目报告
./heredoc-7.sh 

广告

此脚本没有可见的输出。 但是当我们检查我们的邮件时,我们会看到这封电子邮件是撰写、发送和传递的。

 邮件

通过 SSH 使用 Here Documents

建立 SSH 连接后,这里的文档是一种在远程计算机上执行某些命令的强大而方便的方法。 如果您在两台计算机之间设置了 SSH 密钥,则登录过程将是全自动的。 在这个快速而肮脏的示例中,系统将提示您输入远程计算机上用户帐户的密码。

这个脚本是“heredoc-8.sh”。 我们将连接到名为“remote-pc”的远程计算机。 该用户帐户称为“dave”。 我们使用-T (禁用伪终端分配)选项,因为我们不需要为我们分配交互式伪终端。

在脚本的“在这里做一些工作”部分,我们可以传递一个命令列表,这些命令将在远程计算机上执行。 当然,您可以只调用远程计算机上的脚本。 远程脚本可以保存您想要执行的所有命令和例程。

我们的脚本——heredoc-8.sh——要做的就是更新远程计算机上的连接日志。 用户帐户以及时间和日期戳记录到文本文件中。

 #!/bin/bash

ssh -T [email protected] << _remote_commands

# 在这里做一些工作

# 更新连接日志
echo $USER "-" $(date) >> /home/dave/conn_log/script.log
_remote_commands
广告

当我们运行该命令时,系统会提示我们输入远程计算机上帐户的密码。

 ./heredoc-8.sh 

显示有关远程计算机的一些信息,然后我们返回到命令提示符。

远程计算机上,我们可以使用cat查看连接日志:

 猫 conn_log/script.log 

每个连接都为我们列出。

相关:如何从 Linux Shell 创建和安装 SSH 密钥

奇怪的名字,简洁的功能

这里的文档古怪但功能强大,尤其是在用于向远程计算机发送命令时。 使用rsync编写备份例程脚本很简单。 然后,该脚本可以连接到远程计算机,检查剩余存储空间,并在空间不足时发送警报电子邮件。

相关:如何使用 rsync 备份你的 Linux 系统