我的脚本需要运行两个参数。
如果需要它可以有选项,所以我想确保这些属性,所以我写了以下脚本
if [ $# -lt 3 ]
then
echo "This command need 3 arguments"
else
echo $1 $2 $3
fi
观察到“$#”计算传递的参数总数,包括选项
OUTPUT :
sh my_script.sh -o optional1 -r.
它有效,但没有达到预期,因为我的检查失败了。
Expected Output :(two arguments are compulsory)
sh my_script.sh arg1 arg2 --> should work
sh my_script.sh -o optional1 -r optional2 --> throw error that it requires two arguments
sh my_script.sh -o optional1 -r optional2 arg1 arg2 --> should work
答案 0 :(得分:2)
使用getopts
处理选项。
r_flag=0
o_flag="default value"
while getopts o:r arg
do
case "$arg" in
(o) o_flag="$OPTARG";;
(r) r_flag=1;;
(*) echo "Unrecognized option $arg" >&2; exit 1;;
esac
done
循环完成后,使用shift $(($OPTIND - 1))
删除已处理的选项。
现在您可以检查至少还有2个参数:
if [ $# -lt 2 ]
then
echo "Usage: $(basename $0 .sh) [-o option][-r] arg1 arg2 ..." >&2
exit 1
fi
答案 1 :(得分:2)
注意,$#
报告参数数量(positional parameters
)。它并不关心它们是什么。命令行上的任何内容都被视为参数。 (例如somevar
或-o
)。因此,要区分-foo
和foo
,您需要编写解释器,或者使用其他人提供的getopts
(作为解释器)
虽然getopts
没问题,但我通常需要自己的翻译。要在sh
中提供自定义解释器,您通常会使用while loop
,shift
和case
语句来检查每个位置参数并做出相应的响应。虽然与sh
相比,bash
中的字符串操作有限,但这已足够。
符合您要求的示例可能是:
#!/bin/sh
if [ $# -lt 2 ]; then
printf "This command need 2 arguments\n"
exit 1
fi
let nargs=0
while [ "$1" != "" ]; do
printf " processing: %s\n" "$1"
case "$1" in
-r ) shift
[ "$1" = "" -o `expr index "$1" "-"` -eq 1 ] && \
{ printf "error: -r requires an option.\n"; exit 1; }
r_var="$1"
printf " -r %s\n" "$r_var"
let nargs=$nargs+1
;;
-* ) ;; ## don't count '-x' arguments as options (change as needed)
* ) let nargs=$nargs+1
;;
esac
shift
done
if [ $nargs -lt 2 ]; then
printf "\n Two compulsory arguments not given.\n\n"
exit 1
else
printf "\n required arguments satisfied.\n\n"
fi
exit 0
示例使用/输出
$ sh params.sh arg1 arg2
processing: arg1
processing: arg2
required arguments satisfied.
$ sh params.sh -o optional -r
processing: -o
processing: optional
processing: -r
error: -r requires an option.
$ sh params.sh -o optional -r arg1 arg2
processing: -o
processing: optional
processing: -r
-r arg1
processing: arg2
required arguments satisfied.
$ sh params.sh -o arg2
processing: -o
processing: arg2
Two compulsory arguments not given.
检查重复参数
如果您不想尝试覆盖for
语句中的所有内容,则检查重复项的位置参数的嵌套case
循环可能是检查重复参数的最佳方法。一种方法是检查脚本的开头:
#!/bin/sh
let args=2
## check duplicate arguments
for i ; do
for j in $(seq $args $#); do
printf "i: %s j: %s compare %s %s\n" $i $j $i ${!j} ## delete - just for info
if [ $i = ${!j} ]; then
printf "error: duplicate args [ %s = %s ], exiting.\n" $i ${!j}
exit 1;
fi
done
let args=$args+1
done
exit 0
<强>实例/输出强>
$ sh pdupes.sh a b c d e
i: a j: 2 compare a b
i: a j: 3 compare a c
i: a j: 4 compare a d
i: a j: 5 compare a e
i: b j: 3 compare b c
i: b j: 4 compare b d
i: b j: 5 compare b e
i: c j: 4 compare c d
i: c j: 5 compare c e
i: d j: 5 compare d e
$ sh pdupes.sh a b c d b e
i: a j: 2 compare a b
i: a j: 3 compare a c
i: a j: 4 compare a d
i: a j: 5 compare a b
i: a j: 6 compare a e
i: b j: 3 compare b c
i: b j: 4 compare b d
i: b j: 5 compare b b
error: duplicate args [ b = b ], exiting.
防止接受两次争论
除了上面的循环检查将捕获任何重复之外,您还可以向case
语句添加一个选项,以防止接受两次参数。您是否只想跳过副本或标记并退出,由您决定。对于带有可选参数的-o
,我会尝试类似下面的接受可选参数的内容,测试它不是另一个-x
类型并检查它是否已经设置。如果它通过了所有测试,则设置`o_var并通过设置,它不能再次设置:
-o ) shift
[ "$1" = "" -o `expr index "$1" "-"` -eq 1 -o ! -z $o_var ] && \
{ printf "duplicate value for '-o' received, exiting\n"; exit 1; } || \
o_var="$1" && let nargs=$nargs+1
printf " -o %s\n" "$o_var"
;;
轻微变化控制对重复的响应
有两种方法可以处理多次设置-o
的尝试。第一种是退出参数列表中-o
的任何第二次出现(无论是否尝试设置与-o
关联的可选变量):
-o ) shift
## throw error on any second instance of '-o'
if [ -z "$o_var" ]; then
if [ ! `expr index "$1" "-"` -eq 1 -a "$1" != "" ]; then
o_var="$1"
let nargs=$nargs+1
printf " -o %s\n" "$o_var"
fi
else
printf "error: multiple attempts to set '-o', exiting.\n" "$o_var" "$1"
exit 1
fi
;;
<强>实施例强>
第二次设置-o
的两次尝试都被视为相同:
$ sh params.sh -o foo -r arg1 arg2 -o bar
$ sh params.sh -o foo -r arg1 arg2 -o
processing: -o
-o foo
processing: -r
-r arg1
processing: arg2
processing: -o
error: multiple attempts to set '-o', exiting.
另一种可能性是仅在第二次尝试设置与-o
关联的可选变量时才抛出错误。 (例如,如果第二个-o
无害,请忽略它):
-o ) shift
## throw error only if second instance of '-o' has optional argument
if [ "$1" != "" -a ! `expr index "$1" "-"` -eq 1 ]; then
if [ -z "$o_var" ]; then
o_var="$1"
let nargs=$nargs+1
printf " -o %s\n" "$o_var"
else
printf "error: multiple attempts to set '-o'. (%s, now '%s')\n" "$o_var" "$1"
exit 1
fi
fi
;;
<强>实施例强>
$ sh params.sh -o foo -r arg1 arg2 -o bar
processing: -o
-o foo
processing: -r
-r arg1
processing: arg2
processing: -o
error: multiple attempts to set '-o'. (foo, now 'bar')
$ sh params.sh -o foo -r arg1 arg2 -o
processing: -o
-o foo
processing: -r
-r arg1
processing: arg2
processing: -o
required arguments satisfied.
答案 2 :(得分:2)
没有getopts,但几乎是同样的事情,我更喜欢这种方式,因为它更容易添加长args。
#!/bin/bash
while true;do
case $1 in
'-o'|'--optional')
optional1=$2
shift 2
;;
'-r')
optional2=$2
shift 2
;;
*)
break
;;
esac
done
if [[ $# -lt 2 ]];then
echo Too few args.
exit 1
fi
echo $optional1
echo $optional2
显然它可能更强大,因为这将采用多个相同的标志。