Bash Shell命令行参数的使用

Bash Shell命令行参数的使用

执行脚本的时候我们可能需要一并输入相关的参数供脚本执行,这种在执行脚本时直接跟在脚本名后面的参数称为命令行参数。要是用这些参数,我们需要用到一种特殊变量位置参数。bash shell会将命令行参数依次分配给位置参数,以便在脚本中引用。

1 读取参数

位置参数变量是标准的数字:$0是程序名,$1是第一个参数,$2是第二个参数,依次类推,直到第九个参数$9。多个命令行参数需要使用空格分隔。现有脚本如下:

[root@Centos7T blogscripts]#cat t1.sh
#!/bin/bash
echo "Script name is : $0"
echo "The 1st parameter is : $1"
echo "The 2nd parameter is : $2"
echo "The 3rd parameter is : $3"

该脚本会将脚本名及前三个命令行参数一次打印输入。我们执行脚本并输入参数,执行结果如下:

[root@Centos7T blogscripts]#bash t1.sh 100 200 300
Script name is : t1.sh
The 1st parameter is : 100
The 2nd parameter is : 200
The 3rd parameter is : 300

2 测试参数

在原本需要命令行参数的脚本执行时,如果没有输入相应的参数,或者输入的参数不合适,可能导致脚本运行异常,甚至导致机器崩溃。因此,我们有必要对命令行参数的存在性及合理性进行测试。现有脚本如下:

[root@Centos7T blogscripts]#cat t2.sh
#!/bin/bash
result=`echo " scale=4;1 / $1" | bc`
echo "The reciprocal of $1 is : $result"

该脚本会计算出命令行参数的倒数,并保留4位小数位。我们执行脚本并输入参数,执行结果如下:

[root@Centos7T blogscripts]#bash t2.sh 7
The reciprocal of 7 is : .1428
[root@Centos7T blogscripts]#bash t2.sh 8
The reciprocal of 8 is : .1250

但当我们没有输入参数或者输入参数不合适,脚本执行将出现异常:

[root@Centos7T blogscripts]#bash t2.sh
(standard_in) 2: syntax error
The reciprocal of  is :
[root@Centos7T blogscripts]#bash t2.sh 0
Runtime error (func=(main), adr=9): Divide by zero
The reciprocal of 0 is :

改进后的脚本增加了对参数的测试,将参数不存在或者参数为0进行了排除,代码如下:

[root@Centos7T blogscripts]#cat t2.sh
#!/bin/bash
if [ -z $1 ];then
echo "You should input one parameter"
elif [ $1 -eq 0 ];then
echo "Zero can't be devide"
else
result=`echo " scale=4;1 / $1" | bc`
echo "The reciprocal of $1 is : $result"
fi

测试结果如下:

[root@Centos7T blogscripts]#bash t2.sh
You should input one parameter
[root@Centos7T blogscripts]#bash t2.sh 0
Zero cant be devide
[root@Centos7T blogscripts]#bash t2.sh 3
The reciprocal of 3 is : .3333
[root@Centos7T blogscripts]#bash t2.sh 8
The reciprocal of 8 is : .1250

3 统计参数数量

有些脚本可能需要多个参数,我们就不方便对每一个参数测试其存在性。但是如果可以统计出命令行参数的实际数量,然后与脚本需要的参数数量进行比较,就可以大致判断出命令行参数是否满足脚本的需求。变量$#会自动获取命令行参数的数量,现在通过一个例子观察其用法:

[root@Centos7T blogscripts]#cat t3.sh
#!/bin/bash
if [ $# -ne 4 ];then
echo "You should input 4 parameter"
else
echo "($1+$2)*($3+$4)=$[($1+$2)*($3+$4)]"
fi

脚本需要输入4个参数,两两求个后取二者的乘积。在执行计算前,先将参数的数量与4进行比较。现在,我们测试不输入参数、输入3个、4个、5个参数各自的执行结果:

[root@Centos7T blogscripts]#bash t3.sh
You should input 4 parameter
[root@Centos7T blogscripts]#bash t3.sh 2 3 4
You should input 4 parameter
[root@Centos7T blogscripts]#bash t3.sh 2 3 4 5
(2+3)*(4+5)=45
[root@Centos7T blogscripts]#bash t3.sh 2 3 4 5 6
You should input 4 parameter

4 Shift命令与参数移位

shift命令能够控制命令行参数整体的向左移动。在使用shift命令时,默认情况下它会将每个参数变量向左移动一个位置。例如,变量$3的值会移到$2中,变量$2的值会移到$1中,而变量$1的值则会被删除。当然变量$0的值,也即程序名不会改变。如果某个参数被移出,它的值就被丢弃了,无法再恢复。下面通过一个简单的脚本观察其用法:

[root@Centos7T blogscripts]#cat t4.sh
#!/bin/bash
while [ -n "$1" ];do
echo "$@"
shift
done

该脚本利用while循环结构,将所有的命令行参数输入,同时将命令行参数左移。知道变量$1值为空,循环结束。执行结果如下:

[root@Centos7T blogscripts]#bash t4.sh A B C D E F
A B C D E F
B C D E F
C D E F
D E F
E F
F

但要注意的是,没执行shift命令一次,参数总数会减小1,也即变量$#会减小1。下面的脚本是我在联系中烦的一个错误,现在把它列出来:

[root@Centos7T blogscripts]#cat t5.sh
#!/bin/bash
for((i=1;i <= $#;i++))
do
echo $@
shift
done

变量i作为for循环的计数器,每次执行循环体,打印输出所有的参数并将参数使用shift命令移位。预想中的执行结果类似如下:

A B C D E F
B C D E F
C D E F
D E F
E F
F

但实际执行结果如下:

[root@Centos7T blogscripts]#bash t5.sh A B C D E F
A B C D E F
B C D E F
C D E F

显然,for循环体只执行了三次。但问题出在哪呢?我们使用bash -x调试脚本命令观察脚本的运行过程如下:

[root@Centos7T blogscripts]#bash -x t5.sh A B C D E F
+ (( i=1 ))
+ (( i <= 6 ))
+ echo A B C D E F
A B C D E F
+ shift
+ (( i++ ))
+ (( i <= 5 ))
+ echo B C D E F
B C D E F
+ shift
+ (( i++ ))
+ (( i <= 4 ))
+ echo C D E F
C D E F
+ shift
+ (( i++ ))
+ (( i <= 3 ))

变量i在每次循环执行后都会增加1,然后判断i <= $#。然而在每次判断中,变量$#的值一直再减小,导致当i=4时,i <= $#判断为假,循环结束。因此,循环体只执行了三次。为了修正这个错误,我们可以控制变量i在每次循环体执行后不增加,即去掉i++命令,相信会得到我们期望的结果:

[root@Centos7T blogscripts]#cat t5.sh
#!/bin/bash
for((i=1;i <= $#;))
do
echo $@
shift
done

执行结果如下:

[root@Centos7T blogscripts]#bash t5.sh A B C D E F
A B C D E F
B C D E F
C D E F
D E F
E F
F

当然,默认情况下它shift会将每个参数变量向左移动一个位置,我们也可控制命令行参数一次移动多个位置,只需要给shift命令提供一个参数,指明要移动的位置即可。例如shift 3,每次执行shift 3,命令行参数会左移3位,与此同时,统计三叔个数的变量$#也会减小3。

你可能感兴趣的:(linux,运维)