Я написал сценарий оболочки, который использует команду getopt. Список длинных параметров, предоставляемых команде 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
Дополнение
После того, как я прочитал ответ Джонатана Леффлера, я попробовал несколько тестов — обратите внимание на шаблон двоеточия:
# 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' --
ОБНОВЛЕНИЕ от 26 мая 2014 г. -- тестирование getopt_long(3)
Я создал простую программу на C для тестирования функции getopt_long(3).
В моем исходном коде массив структуры «option», переданный в getopt_long(3), содержит определение трех длинных опций «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) присваивает значение 2 (помеченное как LONG_OPT в исходном коде) в поле «val» каждой «определенной пользователем длинной опции». В случае запуска этого потока массив структур «option» будет выглядеть так:
{ "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.
РЕШЕНИЕ ПРЕДЛОЖЕНИЕ
Поскольку я пока не могу ответить на вопрос 1, я думаю, что исходный код команды getopt(1) может быть изменен для присвоения разных значений в поле «val» для каждой определяемой пользователем длинной опции вместо одного и того же значения 2 (LONG_OPT). Так как getopt_long(3) может возвращать один символ ASCII в случае коротких опций, эти значения должны выпадать из карты ASCII -- val >= 256
/usr/gnu/bin/getopt -o a:p: --long localaddress:,localport: -- --local 172.30.2.4 --loc 10.1.2.3
и получил вывод (две строки):/usr/gnu/bin/getopt: option `--local' is ambiguous
и/usr/gnu/bin/getopt: option `--loc' is ambiguous
. Здесь используетсяgetopt (enhanced) 1.1.4
(из/usr/gnu/bin/getopt --version
) — скомпилировано в Mac OS X (работает на 10.9.3, но построено на более ранней версии). - person Jonathan Leffler   schedule 16.05.2014