bash中使用脚本参数
如何传递参数并将其存储到Shell脚本?如何解析shell脚本中的输入参数?如何在bash的shell脚本中将参数传递给函数?如何在Shell脚本中读取命令行参数?
在本教程中,我们将涵盖这些问题,其中涉及具有多个场景和示例的bash脚本参数。我将尽可能详细,以使即使Linux初学者也可以轻松理解该概念。
如何在bash shell脚本中解析输入参数
通常,我们使用这种语法将参数传递给脚本
~]# ./eg_1.sh first second third fourth
现在将所有这些参数存储在脚本中的单个变量中,我们可以使用$@
但是要将这些参数存储在单个变量中,可以根据输入参数的数字位置分配值。我们可以检查该示例脚本,其中我在单个变量中最多存储4个参数。我们可以为变量使用任何名称,为了更好的理解,我使用了这些名称。其中:第4位之后的所有参数都将被忽略。
让我们执行以下脚本:
~]# ./eg_1.sh first second third fourth Input argument list: First argument: first Second argument: second Third argument: third Fourth argument: fourth
因此,正如预期的那样,脚本已成功存储了输入参数并将其打印在屏幕上
方法1:使用if条件和while循环解析输入参数
在此示例中,我们将使用if条件来解析输入参数并执行相应的操作。其中:我编写了一个小脚本,该脚本有望收集以下输入参数
-h或者--help应该打印用法功能
-r [RPM]
或者--rpm [RPM]
只会在控制台上打印提供的rpm名称。-s [VAL]
或者--sleep [VAL]
只会[在控制台上打印sleep值
让我们了解一下此脚本:
"第3行"到"第12行"是我的用法,应该足够清楚。
第14行
如果[! -z" $1"]
条件,该条件将确保继续检查我们的if条件,直到没有其他输入参数为止。
这是一个更可靠的解决方案,而不是将单个参数分配给变量,因为其中我们不必担心输入参数的顺序。
"第15行"将检查第一个输入参数的" --help"或者" -h",如果找到,它将打印"第16行"的用法功能内容。
第17行将在提供的第一个参数中检查-r或者--rpm,如果找到,则将第二个输入参数和$2存储到第18行的RPM_NAME变量中。
第19行将打印$RPM_NAME变量的内容
第20行用于对位置进行"平移",因此下次不必使用" $3",因为这可能会造成混乱,并且很多事情都可能出错,因此在处理输入参数时平移非常重要
第21行将在第一个输入参数中检查-s或者--sleep,如果找到第二个输入参数,将在第22行使用$2参数将其存储在SLEEP变量中。
第23行将打印在第22行收集的SLEEP值。
" 24行"再次很重要,因为我们将执行" shift"操作
如果通过打印
usage
函数未找到匹配的输入参数,则将执行"第25行"至" 28"行"第29行"再次包含" shift",以确保脚本不会以无限循环结束
第30行将结束while循环
我们可以通过调整输入参数的顺序来执行脚本,该脚本仍然可以正常工作。尽管我不是这种方法的忠实拥护者,因为它非常凌乱,并且如果输入参数的数量大于3,则我更希望使用if条件。
~]# ./eg_1.sh -r kernel -s 10 rpm name is kernel sleep value is 10 ~]# ./eg_1.sh -s 10 -r kernel sleep value is 10 rpm name is kernel
使用输入参数时,何时应使用" shift"
我们可能会感到困惑,就像在使用输入参数时何时应使用
shift
一样。如果输入参数不期望各个参数的值,那么我们可以忽略shift,因为我们可以看到在上面的脚本中我没有在
-h
或者--help
中使用过shift
。如果我们使用循环来解析参数,则必须根据需要使用shift。如果输入参数不期望值,则仅在循环结束时才需要移位。
考虑一个场景,其中我们必须收集约10个输入参数,其中一些可能期望各个参数的输入值,因此使用$1,$2..来收集输入参数将非常困难
因此,我们将
while
循环与shift操作配合使用,以便该循环将迭代可用的输入参数使用
while
循环,我们将始终对输入arg和arg的值处理$1
和$2
,因此解决方案更加简洁一旦有了值,就可以执行shift,所以我们再次从$1开始。
如果只需要收集2-3个输入参数,则可以避免移位,如果这对我们来说太复杂了。
方法2:使用case语句和while循环解析输入参数
在这个例子中,我们将使用带有while
循环的case语句来检查输入参数。如我们所见,与带有" if"条件的脚本相比,该脚本看起来更简洁:
while [ ! -z "" ];do case "" in -h|--help) show_usage ;; -r|--rpm) shift RPM_NAME="" echo "rpm name is $RPM_NAME" ;; -s|--sleep) shift SLEEP="" echo "sleep value is $SLEEP" ;; *) echo "Incorrect input provided" show_usage esac shift done
我认为不需要逐行解释脚本的这一部分。这里我已经切换了shift的位置,所以现在如果$1匹配条件,例如-r或者--rpm,那么我执行shift,所以第二个参数对我来说是第一个,所以我存储了将第一个参数放入" RPM_NAME"并打印相同的内容
我们可以执行脚本并以任何可能的顺序进行验证:
~]# ./eg_1.sh -s 10 -r kernel sleep value is 10 rpm name is kernel ~]# ./eg_1.sh -r kernel -s 10 rpm name is kernel sleep value is 10
使用bash脚本参数处理异常和错误
方案1:输入参数缺少值
在以上所有示例中,我们还研究了成功的用例。但是,如果我们期望输入参数带有值,而用户却忘记了传递值,该怎么办?在这种情况下,整个循环可能会中断。让我们使用上面的case语句来演示这一点:
~]# ./eg_1.sh -r -s 10 rpm name is -s Incorrect input provided Usage: ./eg_1.sh [options [parameters]] Options: -r|--rpm [rpm_name], Print rpm name -s|--sleep, Provide the value to sleep -h|--help, Print help
不出所料,我没有给出-r的值,因此将-s视为rpm名称,然后将10视为输入参数。由于我们尚未将10定义为受支持的输入arg,因此脚本失败并打印了usage函数。
因此,处理此类错误情况非常重要。现在,处理情况可能因情况而异。例如,如果我们只希望整数作为某些输入参数的值,则可以添加该检查,让我为我们展示一些示例:
在此脚本中,我添加了以下添加检查:
[[ $RPM_NAME =~ ^- ]] && echo "$RPM_NAME is not a proper value for -r|--rpm" && show_usage [[ $SLEEP =~ ^- ]] && echo "$SLEEP is not a proper value for -s|--sleep" && show_usage
因此我们知道所有输入参数都以连字符开头,因此,如果输入参数的值以连字符开头,则表示未提供值。
让我们测试一下这个脚本,这次它可以完美地工作:
~]# ./eg_1.sh -r -s 10 -s is not a proper value for -r|--rpm Usage: ./eg_1.sh [options [parameters]] Options: -r|--rpm [rpm_name], Print rpm name -s|--sleep, Provide the value to sleep -h|--help, Print help
方案2:计算输入参数列表
失败的另一种可能情况是,我们期望只有2个输入参数,但是用户提供的输入参数要多于2个,因此我们应该对支持的参数进行检查:
其中:我们将计算最小支持的参数列表,如果该列表大于3,则显示一条带有use部分的消息并退出:
if [ $# -gt 3 ];then echo "Only 3 input arguments supported" show_usage exit 1 fi while [ ! -z "" ];do case "" in -h|--help) show_usage ;; <output trimmed>
让我们验证一下脚本:
# ./eg_1.sh -r -s 10 -a Only 3 input arguments supported Usage: ./eg_1.sh [options [parameters]] Options: -r|--rpm [rpm_name], Print rpm name -s|--sleep, Provide the value to sleep -h|--help, Print help
方案3:在不带任何参数的情况下执行脚本时
同样,如果用户在没有任何输入参数的情况下执行脚本,该怎么办?在这种情况下,我们也应该通过显示用法部分退出:
if [[ $# -gt 3 ]] || [[ $# -eq 0 ]];then echo "Either 0 or more than 3 input arguments provided which is 不支持" show_usage exit 1 fi while [ ! -z "" ];do case "" in -h|--help) show_usage ;; <output trimmed>
所以我在相同的if条件中又添加了一个检查,让我们验证一下此脚本:
~]# ./eg_1.sh Either 0 or more than 3 input arguments provided which is 不支持 Usage: ./eg_1.sh [options [parameters]] Options: -r|--rpm [rpm_name], Print rpm name -s|--sleep, Provide the value to sleep -h|--help, Print help
同样,我们可以根据需要添加多个检查。