Command getopt找不到模棱两可的可选参数
我写了一个使用getopt命令的shell脚本。提供给getopt命令的长选项列表包括以下三个不同选项:Command getopt找不到模棱两可的可选参数,command,options,getopt,ambiguous,getopt-long,Command,Options,Getopt,Ambiguous,Getopt Long,我写了一个使用getopt命令的shell脚本。提供给getopt命令的长选项列表包括以下三个不同选项: localaddress localport listen 当我用 myscript.sh --local xxxx 它显然包含一个不明确的选项(--local),getopt将其返回为'--local address'和零代码 ++ getopt -o a:p: --long localaddress:,localport: -- --local 172.30.2.4 + AUX='-
localaddress
localport
listen
当我用
myscript.sh --local xxxx
它显然包含一个不明确的选项(--local),getopt将其返回为'--local address'和零代码
++ getopt -o a:p: --long localaddress:,localport: -- --local 172.30.2.4
+ AUX='-- --localaddress '\''172.30.2.4'\'
但是如果我尝试
myscript.sh --l xxxx
在这里,getopt确实发现它不明确:
getopt: option `--l' is ambiguous
我认为这种行为很奇怪,因为getopt(1)的手册页面显示:
我错过了什么
先发制人
p.D:在RHEL5中测试
附录
在阅读了Jonathan Leffler的答案后,我尝试了一些测试——注意冒号模式:
# getopt -V
getopt (enhanced) 1.1.4
# getopt -o a:p: --long localaddress,localport,listen -- --l xxx
--localaddress -- 'xxx'
# getopt -o a:p: --long localaddress,localport,listen: -- --l xxx
getopt: option `--l' is ambiguous
-- 'xxx'
# getopt -o a:p: --long localaddress,localport:,listen -- --l xxx
getopt: option `--l' is ambiguous
-- 'xxx'
# getopt -o a:p: --long localaddress,localport:,listen: -- --l xxx
getopt: option `--l' is ambiguous
-- 'xxx'
# getopt -o a:p: --long localaddress:,localport,listen -- --l xxx
getopt: option `--l' is ambiguous
-- 'xxx'
# getopt -o a:p: --long localaddress:,localport,listen: -- --l xxx
getopt: option `--l' is ambiguous
-- 'xxx'
# getopt -o a:p: --long localaddress:,localport:,listen -- --l xxx
getopt: option `--l' is ambiguous
-- 'xxx'
# getopt -o a:p: --long localaddress:,localport:,listen: -- --l xxx
--localaddress 'xxx' --
2014-05-26更新——测试getopt_long(3)
我创建了一个简单的C程序来测试getopt_long(3)函数
在我的源代码中,传递给getopt_long(3)的结构“option”数组包含三个长选项“xxaaa”、“xxxy”和“xxxzz”的定义——它们都以相同的字符串“xx”开头,以测试getopt_long(3)检测不明确选项的能力
/*
FIELD NAMES OF option STRUCTURE
name has_arg flag val
*/
{ "xxaaa", no_argument, NULL, 9},
{ "xxxyy", no_argument, NULL, 7},
{ "xxxyz", no_argument, NULL, 7},
{ "mmmAA", no_argument, NULL, 3},
{ "mmmBB", required_argument, NULL, 3},
(有关这些字段用途的详细信息,请参阅getopt_long(3)的手册页)
请注意,一个模棱两可的选项--xx有三个可能的候选者,但是--xxx只有两个候选者
getopt_long的行为根据名为“has_arg”和“val”的两个结构字段的值而变化:
根据上述示例:
test 1. "--xxx" is WRONGLY admitted as "--xxxyy".
test 2. "--xx" is properly refused as ambiguous.
test 3. "--mmm" is properly refused as ambiguous.
getopt(1)命令在每个“用户定义的长选项”的“val”字段中指定一个2(在源代码中标记为LONG_OPT)。在启动此线程的情况下,“选项”结构的数组如下所示:
{ "localaddress", required_argument, NULL, 2},
{ "localport", required_argument, NULL, 2},
因此,getopt(1)检测不明确长选项的唯一方法是候选项在其“has_arg”字段中具有不同的值
问题
Q1. Why does getopt_long(3) behave that way?
Q2. Why does getopt_long_only(3) not?
Q3. How can the creators of getopt_long(3) be notified? -- I'm not into the linux kernel
development nor I do not use to visit linux kernel websites.
变通建议
由于我还不能回答Q1,我认为可能会修改getopt(1)命令的源代码,以便在“val”字段中为每个用户定义的长选项分配不同的值,而不是相同的2(long_OPT)值。由于getopt_long(3)可以在短选项的情况下返回单个ASCII字符,因此这些值应该不属于ASCII映射——val>=256非常奇怪!我至少名义上运行的是同一版本的
getopt
(当然不是RHEL5,RHEL5已经相当老了,现在,IIRC——年龄与它没有多大关系),但我无法重现您得到的结果。对于附录中的每一个操作示例,我都会收到警告消息getopt:option`--l'不明确(并且getopt
的退出状态为1,表示失败)
测试脚本
示例输出
这是自洽的,并且与文档一致。你能运行显示的脚本并验证输出吗?当我测试它时,我运行了:/usr/gnu/bin/getopt-o a:p:--长本地地址:,本地端口:--本地172.30.2.4--loc 10.1.2.3
,我得到了输出(两行):/usr/gnu/bin/getopt:option`--local'不明确
,/usr/gnu/bin/getopt:option`--loc'不明确
。这是使用在Mac OS X上编译的getopt(增强版)1.1.4
(来自/usr/gnu/bin/getopt--version
)(运行在10.9.3上,但构建在早期版本上)。结果是:第一个测试和最后一个测试报告0(不含糊不清),其他测试报告1(含糊不清)。在RHEL 4(getopt 1.1.3)、RHEL 5(getopt 1.1.4)和RHEL 6.4(getopt 1.1.4)中测试。非常奇怪。我无法解释你所看到的。你没有去修补$IFS
,是吗?没有,乔纳森,我没有。建议:获取源代码并编译它,然后看看使用它是否会得到不同的结果。它应该是一个“构建修复”版本,而不是一个“bug修复”版本,所以在理论上它不应该有任何区别。或者从相同的URL获取1.1.4版本。您可能需要在build目录中使用/getopt
来调用它。在“2.6.28-19-server#66 Ubuntu SMP”机器中发现了相同的行为——第一次测试和最后一次测试报告0(不含糊),其他测试报告1(含糊不清)。
{ "localaddress", required_argument, NULL, 2},
{ "localport", required_argument, NULL, 2},
Q1. Why does getopt_long(3) behave that way?
Q2. Why does getopt_long_only(3) not?
Q3. How can the creators of getopt_long(3) be notified? -- I'm not into the linux kernel
development nor I do not use to visit linux kernel websites.
for la in '' :
do
for lp in '' :
do
for li in '' :
do
(
set -x
getopt -o a:p: --long localaddress${la},localport${lp},listen${li} -- --l xxx
)
echo $?
done
done
done
+ getopt -o a:p: --long localaddress,localport,listen -- --l xxx
getopt: option `--l' is ambiguous
-- 'xxx'
1
+ getopt -o a:p: --long localaddress,localport,listen: -- --l xxx
getopt: option `--l' is ambiguous
-- 'xxx'
1
+ getopt -o a:p: --long localaddress,localport:,listen -- --l xxx
getopt: option `--l' is ambiguous
-- 'xxx'
1
+ getopt -o a:p: --long localaddress,localport:,listen: -- --l xxx
getopt: option `--l' is ambiguous
-- 'xxx'
1
+ getopt -o a:p: --long localaddress:,localport,listen -- --l xxx
getopt: option `--l' is ambiguous
-- 'xxx'
1
+ getopt -o a:p: --long localaddress:,localport,listen: -- --l xxx
getopt: option `--l' is ambiguous
-- 'xxx'
1
+ getopt -o a:p: --long localaddress:,localport:,listen -- --l xxx
getopt: option `--l' is ambiguous
-- 'xxx'
1
+ getopt -o a:p: --long localaddress:,localport:,listen: -- --l xxx
getopt: option `--l' is ambiguous
-- 'xxx'
1