bash中使用脚本参数

时间:2020-01-09 10:37:29  来源:igfitidea点击:

如何传递参数并将其存储到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

同样,我们可以根据需要添加多个检查。