Command 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='-

我写了一个使用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)的手册页面显示:

我错过了什么

先发制人

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