在本系列的第一篇文章中,你创建了一个非常小的单行 Bash 脚本,并探讨了创建 shell 脚本的原因以及为什么它们是系统管理员最有效的选择,而不是编译后的程序。在第二篇文章中,你开始创建相当简单的模板的任务,你可以将其用作其他 Bash 程序的起点,然后探索了测试它的方法。
本系列四篇文章中的第三篇解释了如何创建和使用简单的帮助函数。在创建帮助功能时,你还将学习如何使用函数以及如何处理命令行选项,例如 -h。
为什么需要帮助?
即使是相当简单的 Bash 程序也应该有一些帮助功能,即使它非常基础。我编写的许多 Bash shell 程序使用频率很低,以至于我忘记了我需要的确切命令语法。其他程序非常复杂,即使我经常使用它们,也需要查看选项和参数。
拥有内置的帮助功能使你无需检查代码本身即可查看这些内容。良好且完整的帮助功能也是程序文档的一部分。
关于函数
Shell 函数是 Bash 程序语句的列表,这些语句存储在 shell 的环境中,并且可以像任何其他命令一样,通过在命令行中键入其名称来执行。Shell 函数也可能被称为过程或子例程,具体取决于你正在使用的其他编程语言。
函数通过使用其名称在脚本或命令行界面 (CLI) 中调用,就像你对任何其他命令一样。在 CLI 程序或脚本中,函数中的命令在被调用时执行,然后程序流序列返回到调用实体,并且该实体中的下一系列程序语句执行。
函数的语法是
FunctionName(){program statements}
通过在 CLI 中创建一个简单的函数来探索这一点。(该函数存储在创建它的 shell 实例的 shell 环境中。)你将创建一个名为 hw 的函数,它代表 “hello world”。在 CLI 中输入以下代码并按 Enter。然后输入 hw,就像你输入任何其他 shell 命令一样
[student@testvm1 ~]$ hw(){ echo "Hi there kiddo"; }
[student@testvm1 ~]$ hw
Hi there kiddo
[student@testvm1 ~]$
好的,我对标准的 “Hello world” 入门有点厌倦了。现在,列出所有当前定义的函数。它们有很多,所以我只显示新的 hw 函数。当从命令行或程序内部调用时,函数执行其编程任务,然后退出并将控制权返回给调用实体,即命令行或脚本中调用语句之后的下一个 Bash 程序语句
[student@testvm1 ~]$ declare -f | less
<snip>
hw ()
{
echo "Hi there kiddo"
}
<snip>
删除该函数,因为你不再需要它了。你可以使用 unset 命令来做到这一点
[student@testvm1 ~]$ unset -f hw ; hw
bash: hw: command not found
[student@testvm1 ~]$
创建帮助函数
在编辑器中打开 hello 程序,并将下面的帮助函数添加到 hello 程序代码中,在版权声明之后但在 echo "Hello world!" 语句之前。此帮助函数将显示程序的简短描述、语法图以及可用选项的简短描述。添加对帮助函数的调用以测试它,并添加一些注释行,这些注释行在函数和程序的主要部分之间提供可视化分隔
################################################################################
# Help #
################################################################################
Help()
{
# Display Help
echo "Add description of the script functions here."
echo
echo "Syntax: scriptTemplate [-g|h|v|V]"
echo "options:"
echo "g Print the GPL license notification."
echo "h Print this Help."
echo "v Verbose mode."
echo "V Print software version and exit."
echo
}
################################################################################
################################################################################
# Main program #
################################################################################
################################################################################
Help
echo "Hello world!"
此帮助函数中描述的选项是我的程序典型的选项,尽管代码中尚无任何选项。运行程序以测试它
[student@testvm1 ~]$ ./hello
Add description of the script functions here.
Syntax: scriptTemplate [-g|h|v|V]
options:
g Print the GPL license notification.
h Print this Help.
v Verbose mode.
V Print software version and exit.
Hello world!
[student@testvm1 ~]$
因为你尚未添加任何逻辑来仅在需要时显示帮助,所以程序将始终显示帮助。由于该函数工作正常,请继续阅读以添加一些逻辑,以便仅在命令行调用程序时使用 -h 选项时才显示帮助。
处理选项
Bash 脚本处理命令行选项(例如 -h)的能力为指导程序和修改其功能提供了一些强大的功能。对于 -h 选项,你希望程序将帮助文本打印到终端会话,然后退出而不运行程序的其余部分。可以使用 while 命令(请参阅 Bash 编程:循环 以了解有关 while 的更多信息)与 getops 和 case 命令结合使用,将处理命令行输入的选项的能力添加到 Bash 脚本中。
getops 命令读取在命令行中指定的任何和所有选项,并创建这些选项的列表。在下面的代码中,while 命令通过为每个选项设置变量 $options 来循环遍历选项列表。case 语句用于依次评估每个选项,并执行相应节中的语句。while 语句将继续评估选项列表,直到所有选项都已处理完毕或遇到退出语句(这将终止程序)。
务必删除 echo "Hello world!" 语句之前的帮助函数调用,以便程序的主体现在看起来像这样
################################################################################
################################################################################
# Main program #
################################################################################
################################################################################
################################################################################
# Process the input options. Add options as needed. #
################################################################################
# Get the options
while getopts ":h" option; do
case $option in
h) # display Help
Help
exit;;
esac
done
echo "Hello world!"
请注意 -h 的 case 选项中 exit 语句末尾的双分号。这是添加到此 case 语句的每个选项所必需的,以分隔每个选项的结尾。
测试
现在测试稍微复杂一些。你需要使用许多不同的选项以及不使用选项来测试你的程序,以查看它的响应方式。首先,在没有选项的情况下进行测试,以确保它按预期打印 “Hello world!”
[student@testvm1 ~]$ ./hello
Hello world!
这有效,现在测试显示帮助文本的逻辑
[student@testvm1 ~]$ ./hello -h
Add description of the script functions here.
Syntax: scriptTemplate [-g|h|t|v|V]
options:
g Print the GPL license notification.
h Print this Help.
v Verbose mode.
V Print software version and exit.
这按预期工作,因此尝试进行一些测试,以查看当你输入一些意外选项时会发生什么
[student@testvm1 ~]$ ./hello -x
Hello world!
[student@testvm1 ~]$ ./hello -q
Hello world!
[student@testvm1 ~]$ ./hello -lkjsahdf
Add description of the script functions here.
Syntax: scriptTemplate [-g|h|t|v|V]
options:
g Print the GPL license notification.
h Print this Help.
v Verbose mode.
V Print software version and exit.
[student@testvm1 ~]$
程序只是忽略没有任何特定响应的任何选项,而不会生成任何错误。但是请注意最后一个条目(选项为 -lkjsahdf):由于选项列表中有一个 h,因此程序会识别它并打印帮助文本。此测试表明,该程序不具备处理不正确输入并在检测到任何不正确输入时终止程序的能力。
你可以向 case 语句添加另一个 case 节,以匹配任何没有显式匹配的选项。此通用 case 将匹配你没有提供特定匹配的任何内容。case 语句现在看起来像这样,以 \? 的 catch-all 匹配作为最后一个 case。任何其他特定 case 都必须位于最后一个 case 之前
while getopts ":h" option; do
case $option in
h) # display Help
Help
exit;;
\?) # incorrect option
echo "Error: Invalid option"
exit;;
esac
done
再次使用与之前相同的选项测试程序,看看它现在如何工作。
你的进展
通过添加处理命令行选项和帮助过程的功能,你已经在本文中完成了很多工作。你的 Bash 脚本现在看起来像这样
#!/usr/bin/bash
################################################################################
# scriptTemplate #
# #
# Use this template as the beginning of a new program. Place a short #
# description of the script here. #
# #
# Change History #
# 11/11/2019 David Both Original code. This is a template for creating #
# new Bash shell scripts. #
# Add new history entries as needed. #
# #
# #
################################################################################
################################################################################
################################################################################
# #
# Copyright (C) 2007, 2019 David Both #
# LinuxGeek46@both.org #
# #
# This program is free software; you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation; either version 2 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program; if not, write to the Free Software #
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #
# #
################################################################################
################################################################################
################################################################################
################################################################################
# Help #
################################################################################
Help()
{
# Display Help
echo "Add description of the script functions here."
echo
echo "Syntax: scriptTemplate [-g|h|t|v|V]"
echo "options:"
echo "g Print the GPL license notification."
echo "h Print this Help."
echo "v Verbose mode."
echo "V Print software version and exit."
echo
}
################################################################################
################################################################################
# Main program #
################################################################################
################################################################################
################################################################################
# Process the input options. Add options as needed. #
################################################################################
# Get the options
while getopts ":h" option; do
case $option in
h) # display Help
Help
exit;;
\?) # incorrect option
echo "Error: Invalid option"
exit;;
esac
done
echo "Hello world!"
务必非常彻底地测试此版本的程序。使用随机输入并查看会发生什么。你还应该尝试测试有效和无效的选项,而不在前面使用破折号 (-)。
下一步
在本文中,你添加了帮助函数以及处理命令行选项以选择性显示它的功能。程序变得稍微复杂了一些,因此测试变得更加重要,并且需要更多测试路径才能完成。
下一篇文章将介绍初始化变量并进行一些健全性检查,以确保程序在正确的条件下运行。
资源
本系列文章部分基于 David Both 的三部分 Linux 自学课程《使用和管理 Linux—从零到系统管理员》的第 2 卷第 10 章。
评论已关闭。