getopt找不到含糊不清的可选参数

时间:2014-05-16 06:38:15

标签: 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 '\''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.

我错过了什么?

提前完成

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”,“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)的手册页。)

注意一个含糊不清的选项,因为“ - XXX”有三个可能的候选者,但“--- 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)命令的源代码,为每个用户定义的long选项在“val”字段中分配不同的值,而不是相同的2(LONG_OPT)值。由于getopt_long(3)在短选项的情况下可以返回单个ASCII字符,这些值应该超出ASCII映射 - val> = 256

1 个答案:

答案 0 :(得分:0)

非常好奇!我至少在名义上运行相同版本的getopt(诚然不在RHEL5上,现在已经很老了,现在,IIRC - 不是那个年龄与它有很大关系),但我不能重现你的结果得到。对于附录中的每个操作示例,我收到警告消息getopt: option `--l' is ambiguous(并且getopt的退出状态为1,表示失败)。

测试脚本

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

这是自洽的,与文档一致。你可以运行显示的脚本并验证输出吗?