大量参数(操作数)在命令行参数传递中排在首位
Posted
技术标签:
【中文标题】大量参数(操作数)在命令行参数传递中排在首位【英文标题】:Mass arguments (operands) at first place in command line argument passing 【发布时间】:2015-04-19 10:44:18 【问题描述】:我使用以下几行(如果不正确,希望这是最佳实践)来处理命令行选项:
#!/usr/bin/bash
read -r -d '' HELP <<EOF
OPTIONS:
-c Enable color output
-d Enable debug output
-v Enable verbose output
-n Only download files (mutually exclusive with -r)
-r Only remove files (mutually exclusive with -n)
-h Display this help
EOF
# DECLARE VARIABLES WITH DEFAULT VALUES
color=0
debug=0
verbose=0
download=0
remove=0
OPTIND=1 # Reset in case getopts has been used previously in the shell
invalid_options=(); # Array for invalid options
while getopts ":cdvnrh" opt; do
echo "Actual opt: $opt"
case $opt in
c)
color=1
;;
d)
debug=1
;;
v)
verbose=1
;;
n)
download=1
;;
r)
remove=1
;;
h)
echo "$HELP"
exit 1
;;
\?)
invalid_options+=($OPTARG)
;;
*)
invalid_options+=($OPTARG)
;;
esac
done
# HANDLE INVALID OPTIONS
if [ $#invalid_options[@] -ne 0 ]; then
echo "Invalid option(s):" >&2
for i in "$invalid_options[@]"; do
echo $i >&2
done
echo "" >&2
echo "$HELP" >&2
exit 1
fi
# SET $1 TO FIRST MASS ARGUMENT, $2 TO SECOND MASS ARGUMENT ETC
shift $((OPTIND - 1))
# HANDLE CORRECT NUMBER OF MASS OPTIONS
if [ $# -ne 2 ]; then
echo "Correct number of mass arguments are 2"
echo "" >&2
echo "$HELP" >&2
exit 1
fi
# HANDLE MUTUALLY EXCLUSIVE OPTIONS
if [ $download -eq 1 ] && [ $remove -eq 1 ]; then
echo "Options for download and remove are mutually exclusive" >&2
echo "$HELP" >&2
exit 1
fi
echo "color: $color"
echo "debug: $debug"
echo "verbose: $verbose"
echo "download: $download"
echo "remove: $remove"
echo "\$1: $1"
echo "\$2: $2"
如果我以mass arguments(不是开关或开关参数)为最后一个参数的脚本方式调用,一切正常:
$ ./getopts.sh -c -d -v -r a b
Actual opt: c
Actual opt: d
Actual opt: v
Actual opt: r
color: 1
debug: 1
verbose: 1
download: 0
remove: 1
$1: a
$2: b
问题是当我想调用脚本时,大量参数是第一个(或者在不使用参数的开关中间的某个地方)
$ ./getopts.sh a b -c -d -v -r
Correct number of mass arguments are 2
OPTIONS:
-c Enable color output
-d Enable debug output
-v Enable verbose output
-n Only download files (mutually exclusive with -r)
-r Only remove files (mutually exclusive with -d)
-h Display this help
或
$ ./getopts.sh -c a b -d -v -r
Actual opt: c
Correct number of mass arguments are 2
OPTIONS:
-c Enable color output
-d Enable debug output
-v Enable verbose output
-n Only download files (mutually exclusive with -r)
-r Only remove files (mutually exclusive with -d)
-h Display this help
我认为根据 (POSIX) 标准这应该没问题,因为以下基本相同的语法在我的系统上按预期工作:
$ cp test1/ test2/ -r
$ cp test1/ -r test2/
我在 Internet 上进行了搜索,但唯一与我的问题相近的是与 C 相关的 this one。
【问题讨论】:
您的观察是正确的:当遇到第一个非选项参数时,getopts 返回退出状态,因此 while 循环结束。我相信getopt
可以以您想要的更灵活的方式工作。
@glennjackman 建议使用 getopts 而不是 getopt。 AFAIK getopt 被认为是过时的。
我不认为 getopt 被认为是过时的。 getopts 更易于使用(IMO:这是我使用的),但它确实会强制您将选项放在所需参数之前,并且您不能使用 --longoptions。
我只是使用普通的case
语句和shift
来获得相同但更通用的效果。
【参考方案1】:
Bash 提供了两种解析参数的方法。
内置命令getopts
是一种更新的、易于使用的解析参数的机制,但它不是很灵活。 getopts
不允许混合选项和批量参数。
外部命令getopt
是一种更古老、更复杂的参数解析机制。它允许长/短选项,并且 gnu 扩展允许混合选项和质量参数。
【讨论】:
【参考方案2】:getopts
一旦检测到非破折号参数(不包括提供给带参数的 dash 参数的参数),就会自动中断 while 循环。 POSIX 标准是先有虚线参数,然后有文件。 --
和 +
也没有这些废话。简单明了。
但是,Linux 不兼容 Unix 或 POSIX。 GNU 实用程序的本质就是比标准的 Unix 实用程序“更好”。更多功能、更多选项和处理方式略有不同。
在 Linux 上,命令行参数可以在许多 GNU 实用程序中在文件之后出现。
例如:
$ cp -R foo bar
在我通过 Unix 认证的 Mac OS X 和 Linux 上工作,但是,
$ cp foo bar -R
仅适用于 Linux。
如果您希望 getopts
像许多 Linux 实用程序一样工作,您需要做一些工作。
首先,您必须自己处理您的参数,而不是依赖$OPTIND
来解析它们。您还需要验证您是否有论据。
我想出了这个作为做你想做的事的例子。
#! /bin/bash
while [[ $* ]]
do
OPTIND=1
echo $1
if [[ $1 =~ ^- ]]
then
getopts :a:b:cd parameter
case $parameter in
a) echo "a"
echo "the value is $OPTARG"
shift
;;
b) echo "b"
echo "the value is $OPTARG"
shift
;;
c) echo "c"
;;
d) echo "d"
;;
*) echo "This is an invalid argument: $parameter"
;;
esac
else
other_arguments="$other_arguments $1"
fi
shift
done
echo "$other_arguments"
只要设置了$*
,我现在就会循环。 (也许我应该使用$@
?)我必须在循环结束时执行shift
。我也每次都将$OPTIND
重置为1
,因为我正在转移自己的论点。 $OPTARG
仍然设置,但我必须再做一个 shift
以确保一切正常。
我还必须在if
语句中验证参数是否以破折号开头或未使用正则表达式。
基本测试表明它有效,但我不能说它没有错误,但它确实让您了解如何处理您的程序。
您仍然可以从 getopts
获得大量动力,但确实需要更多的工作。
【讨论】:
以上是关于大量参数(操作数)在命令行参数传递中排在首位的主要内容,如果未能解决你的问题,请参考以下文章