Linux系统的Shell脚本传参(bash)2022-08-2
Shell传参快速使用脚本
- 简便版
input="$1"
echo ${input}
- 进阶版
getopt方法
ARGS=$(getopt -a -o i:t::h -l input:,test::,help -- "$@")
eval set -- "${ARGS}"
#help function
function usage() {
echo -e "OPTIONS:\n-i|--input:\t input value"
echo -e "-t|--test:\t Test value"
echo -e "-h|--help:\t Usage information"
echo -e "-o|--output:\t Output value"
exit 1
}
#get value
while true
do
case "$1" in
-i|--input)
input="$2"
shift
;;
-t|--test)
test="$2"
;;
-o|--output)
output="true"
;;
-h|--help)
usage
;;
--)
shift
echo -e "\nUnused option(s): $@"
break
;;
esac
shift
done
#default value
test=${test:="test0"}
output=${output:="false"}
echo 'Input value:'$input
echo 'Test value:'$test
echo 'Output value:'$output
getopts方法
#default value
input='0'
test=${test:="test0"}
output=${output:="false"}
#help function
function usage() {
echo -e "OPTIONS:\n-i|--input:\t input value"
echo -e "-t|--test:\t Test value"
echo -e "-h|--help:\t Usage information"
echo -e "-o|--output:\t Output value"
exit 1
}
#get value
while getopts :i:t::ho opt
do
case "$opt" in
i) input="$OPTARG" ;;
t) test="$OPTARG" ;;
h) usage ;;
o) output="true" ;;
:) echo "This option -$OPTARG requires an argument."
exit 1 ;;
?) echo "-$OPTARG is not an option"
exit 2 ;;
esac
done
echo 'Input value:'$input
echo 'Test value:'$test
echo 'Output value:'$output
做生信一般都绕不开Shell脚本编写,如果脚本可以传参就能实现大批量任务投递,而且也可以通过传参把相关流程封装起来,相当于与一个包或模块,用起来也比较方便。然而Shell脚本又不像R和Python等语言,有现成包或模块可以简单快速实现传参(我之前写了R语言和Python传参的文章,感兴趣可以点进去看一下。),不过其实Shell传参也没有特别复杂,简单学习一下也能快速上手。最简单的传参就是使用$1,$2这种形式,分别代表第一个和第二个参数,但是如果参数多起来就不太方便了,还是有名字的参数比较方便。
getopt与getopts简介
getopt和getopts都是Shell自带的命令行参数解析工具,应该就类似于awk和sed工具,但两者用法稍有不同,前者能实现更多功能,例如支持长名称,而后者不支持,但getopts使用起来稍微简单些,不用使用shift命令,更详细的内容看一查看这篇博客。
getopt传参
getopt可以在命令行直接使用
getopt --alternative a: -a test
--alternative表示允许长名称,可简写为-a,--option(-o)后面接短名称,--long(-l)后面接长名称。短名称由单个字母和0-2个冒号组成,例如i,i:,i::,如果只有冒号没有字母,表示如果不指定选项传参的情况出现,忽略错误,短名称与冒号组合后直接写到一起,例如i:t::ho,对应的长名称要按顺序并且冒号数目要对应,并以逗号分隔。--表示后面的内容都会视为一个输入参数。
- 参数后面冒号个数的含义:0个表示不接受参数,1个表示必须接受参数,2个表示可接也可不接受参数。注意2个冒号的可选参数如果要传参需要写成-ttest形式,写成-t test或-t=test都不行。
在脚本中使用getopt
- 第一步,首先,构建参数变量,使用getopt先定义参数,然后获取外部参数数组传给变量ARGS。$@表示传入的所有参数。
ARGS=$(getopt --alternative --option :i:t::ho --long :input:,test::,help,output -- "$@")
eval set -- "${ARGS}"
set命令可以模拟传参过程,用法是set -- $(getopt a "$@"),相当于把getopt从命令行获取产出处理后的结果传给set,但由于是二次处理的参数结果,如果出现复杂的参数(例如有空格的参数)就会出现问题,因此需要eval命令把后面的内容作为单个命令读取和执行。
- 第二步,构建帮助信息函数
function usage() {
echo -e "OPTIONS:\n-i|--input:\t input value"
echo -e "-t|--test:\t Test value"
echo -e "-h|--help:\t Usage information"
echo -e "-o|--output:\t Output value"
exit 1
}
-
第三步,获取参数值
shift命令可以把第一个参数去电,使得第二个参数变成第一个参数,以此类推。因此,可以通过shift函数结合while循环逐个获取参数。
while true
do
case "$1" in
-i|--input)
input="$2"
shift
;;
-t|--test)
test="$2"
;;
-o|--output)
output="true"
;;
-h|--help)
usage
;;
--)
shift
echo -e "\nUnused option(s): $@"
break
;;
esac
shift
done
-
第四步,设置默认值
这里的逻辑是先检测变量是否为空,如果为空则赋默认值,使用:=实现给变量设置默认值可以查看这篇博客。
当然,其实也可以先在上述循环前直接给变量赋值。
test=${test:="test0"}
output=${output:="false"}
示例1
test.sh内容
ARGS=$(getopt --alternative --option :i:t::ho --long :input:,test::,help,output -- "$@")
#ARGS=$(getopt -a -o i:t::h -l input:,test::,help -- "$@")
eval set -- "${ARGS}"
function usage() {
echo -e "OPTIONS:\n-i|--input:\t input value"
echo -e "-t|--test:\t Test value"
echo -e "-h|--help:\t Usage information"
echo -e "-o|--output:\t Output value"
exit 1
}
while true
do
case "$1" in
-i|--input)
input="$2"
shift
;;
-t|--test)
test="$2"
;;
-o|--output)
output="true"
;;
-h|--help)
usage
;;
--)
shift
echo -e "\nUnused option(s): $@"
break
;;
esac
shift
done
test=${test:="test0"}
output=${output:="false"}
echo 'Input value:'$input
echo 'Test value:'$test
echo 'Output value:'$output
运行脚本
~ $ sh test.sh -h
OPTIONS:
-i|--input: input value
-t|--test: Test value
-h|--help: Usage information
-o|--output: Output value
~ $ sh test.sh -i 1
Unused option(s):
Input value:1
Test value:test0
Output value:false
~ $ sh test.sh -i 1 -ttest1
Unused option(s):
Input value:1
Test value:test1
Output value:false
getopts传参
getopts只支持短名称选项,但不需要额外的命令操作就能获取参数,其涉及3个变量:
OPTIND: 存放下一个要处理的参数的索引。这是 getopts 在调用过程中记住自己状态的方式。
OPTARG: 由 getopts 找到的选项所对应的参数。
OPTERR: 值为0或1。指示Bash是否应该显示由 getopts 产生的错误信息。
其它步骤与上述内容相同,只有解析参数的循环不一样,相较而言简单很多,不用使用shift,而是直接使用变量OPTARG。
while getopts :i:t::ho opt
do
case "$opt" in
i) input="$OPTARG" ;;
t) test="$OPTARG" ;;
h) usage ;;
o) output="true" ;;
:) echo "This option -$OPTARG requires an argument."
exit 1 ;;
?) echo "-$OPTARG is not an option"
exit 2 ;;
esac
done
示例2
test1.sh内容
input='0'
test=${test:="test0"}
output=${output:="false"}
function usage() {
echo -e "OPTIONS:\n-i|--input:\t input value"
echo -e "-t|--test:\t Test value"
echo -e "-h|--help:\t Usage information"
echo -e "-o|--output:\t Output value"
exit 1
}
while getopts :i:t::ho opt
do
case "$opt" in
i) input="$OPTARG" ;;
t) test="$OPTARG" ;;
h) usage ;;
o) output="true" ;;
:) echo "This option -$OPTARG requires an argument."
exit 1 ;;
?) echo "-$OPTARG is not an option"
exit 2 ;;
esac
done
echo 'Input value:'$input
echo 'Test value:'$test
echo 'Output value:'$output
运行脚本
~ $ sh test1.sh -h
OPTIONS:
-i|--input: input value
-t|--test: Test value
-h|--help: Usage information
-o|--output: Output value
~ $ sh test1.sh -i 1
Input value:1
Test value:test0
Output value:false
~ $ sh test1.sh -i 1 -ttest1 -o
Input value:1
Test value:test1
Output value:true