[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

 

本节结束、

 

posted @ 2020-05-28 14:39  workingdiary  阅读(842)  评论(0)    收藏  举报