我写了一个使用 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 '\''172.30.2.4'\'
但如果我尝试
myscript.sh --l xxxx
这里 getopt 确实发现它模棱两可:
getopt: option `--l' is ambiguous
鉴于 getopt(1) 的手册页显示,我认为这种行为很奇怪:
Long options may be abbreviated, as long as the abbreviation is not ambiguous.
我错过了什么?
提前感谢
PD:在 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”、“xxxyy”和“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”的两个结构字段的值而变化:
WHEN
the value of "val" field is the same in every possible candidate
AND
the value of the "has_arg" field is the same in every possible candidate,
THEN
the function getopt_long wrongly complains NOTHING about ambiguity
and the first candidate is returned
OTHERWISE
an error message about ambiguity is reported.
从上面的例子:
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