bash 参数传递与获取
写脚本的时候,难免需要传递参数,这时需要知道在shell中如何获取参数并且解析
基础用法
echo $n # 按照顺序传递的第几个参数,从0开始索引,脚本自己也作为一个参数传递,所以$0就是脚本自己
echo $# # 参数个数,不包括脚本自己
echo $* # 所有参数,是一个字符串
echo $@ # 所有参数,是一个数组
bash test.sh -a b --c=d
$0 test.sh
$1 -a
$2 b
$3 --c=d
$# 3
$*/$@ -a b --c=d
getopts
上面的方法,函数少的时候,可以应付;函数多的话就比较麻烦了,这时候可以使用getopts实现
#!/bin/bash
while getopts 'a:b:c:d' opts; do
case $opts in
a) echo $OPTARG;;
b) echo $OPTARG;;
?) echo 'aaa';;
esac
done
上面就是通过getopts从脚本参数中获取a b c d开头指定的参数,如果传递了没有指定的参数会报错,?就是捕获这种参数。OPTARG是指定参数所赋的值,会保存在这个里面
bash test.sh -a abc -f a
abc
test.sh:非法选项 -- f
aaa
shift
shift会把参数序号减一,也方便我们自己解析
#!/bin/bash
until [ -z "$1" ]
do
case "$1" in
-a)
echo "$2"
shift;;
-b)
echo "$2"
shift;;
-c)
echo "$2"
shift;;
*)
echo "xxx"
exit 0
esac
shift
done
case的*是匹配所有,util是直到条件不满足就终止循环,-z就是判断参数是否是zero,也就是空
bash test.sh -a abc -b bbb -f ccc
abc
bbb
xxx
getopt
https://www.tutorialspoint.com/unix_commands/getopt.htm
使用getopts无法解析--的参数,getopt功能更强大,可以支持--,看一下官方的示例
#!/bin/bash
# read the options
# -o 指定短选项参数有哪些,参数后面不加冒号,就表示这个参数没有值;参数后面有一个冒号,就表示这个参数必须有一个值,格式随意-fMyfile.txt -f Myfile.txt -f=Myfile.txt都可以,实际上-fMyfile.txt和-f=Myfile.txt情形一样,-f并不在意=,只是把它作为参数的值,-f=Myfile.txt的值就是=Myfile.txt;参数后面有两个冒号,表示可以有一个值,值必须紧贴参数,也可以不写值,-s -sSource.txt都对
# --long 就是两个短横线的长参数
TEMP=`getopt -o f:s::d:a:: --long file-name:,source::,destination:,action:: -- "$@"`
# 这一句正常加上就可以,排序,把没有值的参数放后面
eval set -- "$TEMP"
# extract options and their arguments into variables.
# 遍历获取参数和其值
while true ; do
case "$1" in
-f|--file-name)
fileName=$2 ; shift 2 ;;
-s|--source)
case "$2" in
"") sourceDir='.' ; shift 2 ;;
*) sourceDir=$2 ; shift 2 ;;
esac ;;
-d|--destination)
destinationDir=$2 ; shift 2;;
-a|--action)
case "$2" in
"copy"|"move") action=$2 ; shift 2 ;;
*) action="copy" ; shift 2 ;;
esac ;;
--) shift ; break ;;
*) echo "Internal error!" ; exit 1 ;;
esac
done
# Now take action
echo "$action file $fileName from $sourceDir to $destinationDir"
bash test.sh -f MyFile.txt -s/home -d /home/test -aMove
Move file MyFile.txt from /home to /home/test
bash test.sh --file-name MyFile.txt --source=/home --dest /home/test --act=Move
Move file MyFile.txt from /home to /home/test
bash test.sh --file-name MyFile.txt --source=/home --dest /home/test --act
Copy file MyFile.txt from /home to /home/test
bash test.sh --file-name MyFile.txt --source=/home -a Move -d
getopt: option requires an argument -- d
Copy file MyFile.txt from /home to
这个的写法是固定的一套,你可以拷贝过去改改就可以用。
注意
每次shift会向后移一位,也就相当于把参数列表的第一位$1丢掉,那么$2就变成了$1.
在遍历的时候一定要注意,如果是参数有值,那么需要再跳一位,因为这一次把$1和$2都用掉了,下一次应该从$3开始;如果参数没值,不要跳多了,导致下一个参数被跳过
只获取长参数
如果想只获取长参数,需要这样写getopt -o "" --long file-name:,source::,destination:,action:: -- "$@"
,必须有-o,如果没有,会导致getopt无法解析第一个参数,不知道是--long