如何在bash中将选项与参数分开?
我的脚本需要两个参数才能运行 如果需要,它可以有选项,所以我想确保这些属性,所以我编写了以下脚本如何在bash中将选项与参数分开?,bash,shell,Bash,Shell,我的脚本需要两个参数才能运行 如果需要,它可以有选项,所以我想确保这些属性,所以我编写了以下脚本 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 Ou
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
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))
删除已处理的选项if [ $# -lt 2 ]
then
echo "Usage: $(basename $0 .sh) [-o option][-r] arg1 arg2 ..." >&2
exit 1
fi
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))
删除已处理的选项if [ $# -lt 2 ]
then
echo "Usage: $(basename $0 .sh) [-o option][-r] arg1 arg2 ..." >&2
exit 1
fi
注意,
$#
报告了参数数(位置参数
)。它不在乎它们是什么。命令行中的任何内容都被视为参数。(例如somevar
或-o
)。因此,为了区分-foo
和foo
,您需要编写一个解释器,或者使用他人提供的getopts
(作为该解释器)
虽然getopts
很好,但我通常需要自己的解释器。要在sh
中提供自定义解释器,通常需要使用while循环
、移位
和case
语句来检查每个位置参数并做出相应的响应。与bash
相比,字符串操作在sh
中有一定的局限性,这就足够了
符合您需求的示例可以是:
#!/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.
$ 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.
检查重复参数
$ 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.
如果您不想尝试覆盖case
语句中的所有内容,那么嵌套的for
循环检查位置参数是否重复可能是检查重复参数的最佳方法。一种方法是在脚本开始时检查:
#!/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 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.
$ 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
关联的可选变量):
示例
$ 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.
第二次设置-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
是无害的,则忽略它):
示例
$ 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.
注意,
$#
报告了参数数(位置参数
)。它不在乎它们是什么。命令行中的任何内容都被视为参数。(例如somevar
或-o
)。因此,为了区分-foo
和foo
,您需要编写一个解释器,或者使用他人提供的getopts
(作为该解释器)
虽然getopts
很好,但我通常需要自己的解释器。要在sh
中提供自定义解释器,通常需要使用while循环
、移位
和case
语句来检查每个位置参数并做出相应的响应。与bash
相比,字符串操作在sh
中有一定的局限性,这就足够了
符合您需求的示例可以是:
#!/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.
$ 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.
检查重复参数
$ 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.
如果您不想尝试覆盖case
语句中的所有内容,那么嵌套的for
循环检查位置参数是否重复可能是检查重复参数的最佳方法。一种方法是在脚本开始时检查:
#!/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 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.
$ 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
关联的可选变量):
示例
$ 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.
两次尝试都设置了