[Linux Shell学习系列十]脚本输入处理-1参数处理
D18
本节介绍如何在Shell脚本中获取和使用传入的命令行参数。
1. 使用case语句处理命令行参数
当脚本只接收一个命令行参数且根据该参数采取不同行为时,通常使用case语句来处理这个命令行参数。
最常见于Linux下的应用程序或服务的启动脚本中。
$ cat backup.sh #!/bin/bash #20200528 case $1 in #单个命令行参数 sql ) echo "Running mysql backup..." ;; sync ) echo "Running sync backup..." ;; snap ) echo "Running snap backup..." ;; * ) echo "Usage: `basename $0` {sql|sync|snap}" ;; esac $ ./backup.sh Usage: backup.sh {sql|sync|snap} $ ./backup.sh sql Running mysql backup... $ ./backup.sh sync Running sync backup... $ ./backup.sh snap Running snap backup...
但是,大小写敏感的模式下,下面的命令是失败的:
$ ./backup.sh Snap Usage: backup.sh {sql|sync|snap}
可以在脚本中开启nocasematch选项(该选项开启后,case或[[]]条件命令时,Shell以大小写不敏感的方式匹配模式)
$ cat backup.sh #!/bin/bash #20200528 shopt -s nocasematch #开启nocasematch模式 case $1 in sql ) echo "Running mysql backup..." ;; sync ) echo "Running sync backup..." ;; snap ) echo "Running snap backup..." ;; * ) echo "Usage: `basename $0` {sql|sync|snap}" ;; esac
shopt -s nocasematch #关闭nocasematch模式
$ ./backup.sh Snap #可以执行snap Running snap backup...
或者可以在case中使用正则表达式匹配参数,但并不方便。
2. 使用shift命令处理命令行参数
需要多个命令行参数时,使用shift命令在一个变量中一个接一个地获取多个命令行参数(特殊变量$0不参与移位操作)。
语法:shift [n] #n必须为小于或等于"$#"的非负整数。
如果为0,位置参数将不会改变;
如果没有指定n,则默认设为1;
如果n大于$#,位置参数同样不会改变;
如果n大于$#或小于0,此命令返回状态码大于0,否则为0。
注意:当使用shift时,位置参入变动的同时,之前的变量值被废弃,后续变量向前传递,且特殊变量$#递减。、
$ cat getParam.sh #!/bin/bash #202005 while [ $# -ne 0 ] do echo "Current Parameter: $1, Remaining $#. Current all paras: $@." #特殊变量$1为第一个变量,$#为变量个数,$@为所有变量 shift done $ ./getParam.sh one two three four five Current Parameter: one, Remaining 5. Current all paras: one two three four five. #每经过一次位移,变量被删除 Current Parameter: two, Remaining 4. Current all paras: two three four five. Current Parameter: three, Remaining 3. Current all paras: three four five. Current Parameter: four, Remaining 2. Current all paras: four five. Current Parameter: five, Remaining 1. Current all paras: five.
上面判断$#值进行循环,也可以通过$1是否为空判断:
$ cat getParam.sh #!/bin/bash #202005 while [ -n "$1" ] #不为空就继续循环 do echo "Current Parameter: $1, Remaining $#. Current all paras: $@." shift done
加入上述的脚本中每次位移3,但输入的只有5个参数,则第一次位移后,就不能再执行位移了,while循环就会一直进行。为了解决这个问题,我们可以使用shift命令的退出状态:通过在shift后加变量$?的值是否为0的检查,如果非0,就可以停止循环。
$ cat shift3Param.sh #!/bin/bash #202005 while [ -n "$1" ] do echo "Current Parameter: $1, Remaining $#. Current all paras: $@." shift 3 if [ $? -ne 0 ] #这里检查shift命令的执行结果,不为0则退出循环 then break fi done $ ./shift3Param.sh one two three four five Current Parameter: one, Remaining 5. Current all paras: one two three four five. Current Parameter: four, Remaining 2. Current all paras: four five.
3. 使用for循环读取多个参数
当输入的参数较多时,常用for循环来一个一个处理所有命令行参数。
可以采用$*或$@获取传递给脚本的所有命令行参数。
$ cat forArgs.sh #!/bin/bash #202005 E_BADARGS=65 if [ ! -n "$1" ] then echo "Usage: `basename $0` argument1 argument2 ..." exit $E_BADARGS fi index=1 #设置序号为1 echo "List args with \$*:" for arg in $* #使用$*,注意这里不加双引号,如果加了就扩展为包含所有位置参数值的单个字符串,将使for循环只有一次 do echo "Arg #$index = $arg" let index+=1 #序号+1 done index=1 #设置序号为1 echo "List args with \$@:" for arg in $@ #使用$@ do echo "Arg #$index = $arg" let index+=1 #序号+1 done $ ./forArgs.sh Usage: forArgs.sh argument1 argument2 ... $ echo $? #返回状态码为E_BADARGS 65 $ ./forArgs.sh one two three List args with $*: Arg #1 = one Arg #2 = two Arg #3 = three List args with $@: Arg #1 = one Arg #2 = two Arg #3 = three $ echo $? #返回状态码为0 0
while或for循环中,也可以与case语句结合使用。(补充下面示例)
$ cat forBackup.sh #!/bin/bash #20200528 E_BADARGS=65 if [ ! -n "$1" ] then echo "Usage: `basename $0` argument1 argument2 ..." exit $E_BADARGS fi shopt -s nocasematch for arg in $* #遍历所有参数 do case $arg in sql ) echo "Running mysql backup..." ;; sync ) echo "Running sync backup..." ;; snap ) echo "Running snap backup..." ;; * ) echo "Usage: `basename $0` {sql|sync|snap}" ;; esac done $ ./forBackup.sh Usage: forBackup.sh argument1 argument2 ... $ ./forBackup.sh snap sync #两个选项都被执行了 Running snap backup... Running sync backup...
4. 读取脚本名
通过特殊变量$0来获取当前Shell脚本的名称,通常用于校验执行环境或变量后显示使用说明。
$ cat checkArgNum.sh #!/bin/bash #202005 ARGS=3 #定义脚本参数的个数 if [ $# -ne "$ARGS" ] #检查命令行参数的个数是否等于3,不等于则显示使用说明并退出 then echo "Usage: `basename $0` param1 param2 param3"
#此处使用$0不仅使脚本更简洁,并且当修改脚本名称时,不需要修改内容,可以形成Usage函数,供多个脚本复用 exit 2 fi $ ./checkArgNum.sh Usage: checkArgNum.sh param1 param2 param3 $ echo $? 2
5. 测试命令行参数
除了检查参数个数,也需要检查参数值、类型、是否存在、是否为可执行等。
$ cat testArg.sh #!/bin/bash #202005 if [ -z "$1" ] #没有输入参数,则提示使用说明 then echo "Usage: `basename $0` parameter1 filename" exit 1 fi ARGS=2 if [ $# -ne $ARGS ] #参数个数错误,提示使用说明 then echo "Usage: `basename $0` parameter1 filename" exit 2 fi varStr=$1 if [ -f "$2" ] #检查参数2指定的文件是否存在 then file_name=$2 echo "$1" >> $file_name else echo "File \"$2\" does not exist." exit 3 fi $ ./testArg.sh #无参数 Usage: testArg.sh parameter1 filename
$ ./testArg.sh a #只输入一个参数
Usage: testArg.sh parameter1 filename
$ ./testArg.sh a a.txt #指定的fileanme不存在
File "a.txt" does not exist.
$ ./testArg.sh a list.txt
$ tail -1 list.txt
a
本节结束、

浙公网安备 33010602011771号