问题描述
我正在使用getopt解析脚本的命令行参数。 所有可选参数(-o和--long)都由getopt处理,但也有强制性参数。参数4可以是路径或值的序列,这些值可以为负。
script.sh mandatory/path/one mandatory/path/two mandatory/file.txt -200.12,32.7,-18.7
如果参数4以负值开头,则-
将触发getopt。显然,这会破坏脚本,因为getopt将抱怨未定义的选项。
我可以想到两种解决方法,但这两种方法都很hacky:
- 在$ @上执行sed操作,以用一些伪字符串替换
-
,然后在解析完成getopt之后再次进行sed操作,以再次用-
替换伪对象。
ARGS=$(echo "$@" | sed -E "s/-([0-9])/%dummy%\1/g")
set -- "$ARGS"
ARGS=`getopt -o n -l no-act -n $0 -- "$@"`
eval set -- "$ARGS"
while :; do
case "$1" in
-n|--no-act)
norun=1 ;;
--)
shift; break ;;
*)
break
esac
shift
done
ARGS=$(echo "$@" | sed -E "s/%dummy%([0-9])/-\1/g")
eval set -- "$ARGS"
- 使用getopt -1234567890中的参数定义选项。这会将强制参数4拆分为
-2
和00.12,-18.7
,可以将其合并为中间变量。最后,必需的参数1-3和4必须再次为set
。
ARGS=`getopt -o n1:2:3:4:5:6:7:8:9:0: -l no-act -n $0 -- "$@"`
eval set -- "$ARGS"
while :; do
case "$1" in
-n|--no-act)
norun=1 ;;
-1|-2|-3|-4|-5|-6|-7|-8|-9|-0)
TEMPVAR=$1$2
shift ;;
--)
shift; break ;;
*)
break
esac
shift
done
必须有一种更优雅的方法来做到这一点。 Getopt在其他方面做得很好,我希望保留它用于命令行解析。
(还有更多选项,我在示例中仅提及-n选项以使代码块简短)
编辑:强制性参数4应该保持为$ 4,因为这行还有进一步的检查。
解决方法
有-种。这里的问题是,getopt
命令除了以连字符开头的选项之外,实际上不了解其他任何内容,也不能说服它使用除连字符以外的其他内容作为选项的领导。无法告诉getopt不要以任何其他方式处理选项。
但是,getopt
不处理参数。它只是将其传递到$OPTARG
变量中,而没有任何解析。因此,这里有三个选项:
- 如果您的选择是固定的,则无需在此处使用
getopt
。只需照常使用$1
,$2
和$3
,然后以错误的计数和/或格式错误的数字列表使脚本失败。您始终可以计算参数的数量,如果需要,可以将最后一个作为列表。 - 另一方面,如果您的选项不是 位置,那么您确实应该考虑为数字列表提供自己的选项,然后专门解释
$OPTARG
。 - 如果您做的很特别,请创建自己的选项分析循环。
getopt
是为完成相对简单的任务而设计的,诸如扩展其用途之类的东西。
以上任何内容通常都可以在有用的脚本中完成。我鼓励您不要使问题复杂化。脚本应该相对简单,并且Bash最好用作命令构造和调度语言。 Bash(也许只是sh
?)是发行版中默认情况下唯一可用的语言,我们生活的时代已不复存在。如果您要进行一些相当复杂的参数处理,则应强烈考虑使用Perl,Python或Ruby之类的通用编程语言是否是您打算做的更好的选择。