Як я можу виявити, що жодних варіантів не було прийнято з getopts?


19

У мене цей код -

#getoptDemo.sh
usage()
{
    echo "usage: <command> options:<w|l|h>"
}
while getopts wlh: option
do
    case $option in
            (w)
                    name='1';;
            (l)
                    name='2';;
            (h)
                    name='3';;
            (*)
                    usage
                    exit;;
    esac
done
print 'hi'$name

Коли я запускаю bash getoptDemos.sh(без опції), він друкує hiзамість виклику функції usage. Він називає використання, коли задані інші варіанти, ніж w, h та l. Тоді чи не може він працювати, коли не вказані варіанти.

Я спробував з допомогою ?, \?, :замість , *але я не можу домогтися того, чого я хотів. Я маю в виду все docsна getoptкаже , що це використовувати ?.

Що я роблю неправильно?


Під якою оболонкою ти працюєш?
Джуліан

Я запускаю його під/bin/bash
Хуссейном Тамболі

Інші альтернативи: wiki.bash-hackers.org/howto/getopts_tutorial
slm

Відповіді:


15

Якщо запустити цей скрипт без будь-яких варіантів, getopt поверне помилковий, тому він взагалі не ввійде в цикл. Це просто впаде до друку - це ksh / zsh?

Якщо у вас є опція, найкраще ставити тест на $ name після циклу.

if [ -z "$name" ]
then
   usage
   exit
fi

Але переконайтеся, що $nameперед викликом було порожнім getopts(оскільки в середовищі могла бути $nameоболонка, отримана при запуску) з

unset name

(перед getoptsциклом)


ні. його баш. Отже, як я досягти того, що хочу - обробити no argumentстан за допомогою bash.
Хуссей Тамболі

Якщо ви хочете обов'язковий варіант, я не думаю, що це можливо - це, ймовірно, тому вони називаються параметрами :) Ви можете протестувати $ name, хоча після циклу, щоб переконатися, що він встановлений. if [-z "$ name"]; потім використання; Вхід ; fi
Джуліан

Спасибі. вищевказаний код справді допоміг. Це занадто погано getoptsне має такого положення. Що гірше, ніж те, що вас не можуть підняти.
Хуссей Тамболі

що робити, якщо я запускав іншу оболонку? зш, ш. чи доглядає за цим станом будь-яка оболонка, окрім Баша?
Хуссей Тамболі

20

getoptsобробляє варіанти по черзі. Це його робота. Якщо користувач не передає жодної опції, перший виклик getoptsвиходить з циклу while.

Якщо жоден з варіантів не бере аргумент, значення OPTINDвказує, скільки варіантів було передано. Загалом, OPTINDце кількість аргументів, які є варіантами або аргументами до опцій, на відміну від аргументів, які не є опціями (операнди).

while getopts …; do …; done
if [ $OPTIND -eq 1 ]; then echo "No options were passed"; fi
shift $((OPTIND-1))
echo "$# non-option arguments"

У будь-якому випадку ви не намагаєтесь визначити, чи не було варіантів, але чи не nameбуло передано жоден із параметрів, що встановлюються. Тому перевірте, чи nameвона не встановлена ​​(і спершу переконайтесь, що її не було) .


1
Спасибі. +1 для вас. коли я поміщую останні 3 рядки з вашого коду в sample.sh і запускаю, bash sample.sh -abc file.txtвін дає - 1 non-option arguments. як я дізнаюся, скільки було надано варіантів. (тут 3)
Хуссейн Тамболі

1
Дивно, що ніхто не коментував цю незначну помилку - якщо параметри не вказані, OPTIND після цього буде циклом "поки getopts ...". Таким чином, якщо чек повинен перевірити рівність з 1, а не з нулем.
Даніель

4

Якщо ваш сценарій повинен отримати аргументи опцій у будь-якому випадку, поставте цей блок на початку (перед getops).

if [[ ! $@ =~ ^\-.+ ]]
then
  #display_help;
fi

Блок перевіряє, що рядок параметра не починається -символом, що вказує, що перший параметр не є аргументом опції.


2

Я перевірив би це зі змінною. Якщо getopts ніколи не передає цикл у разі відсутності аргументу, ви можете використовувати його, наприклад, наприклад:

#getoptDemo.sh
usage()
{
    echo "usage: <command> options:<w|l|h>"
}

no_args="true"
while getopts wlh: option
do
    case $option in
            (w)
                    name='1';;
            (l)
                    name='2';;
            (h)
                    name='3';;
            (*)
                    usage
                    exit;;
    esac
    no_args="false"
done

[[ "$no_args" == "true" ]] && { usage; exit 1; }

print 'hi'$name

0

Перед getoptsблоком перевірте, чи $1(перший аргумент / варіант, який ви передали в командному рядку), дорівнює порожній рядку. Якщо це так, надрукуйте повідомлення про використання та вийдіть (або виконайте якусь функцію "без параметрів", якщо ви анархіст), інакше дозвольте getoptsпроаналізувати параметри, як звичайні.

Причина, що ця функція не включена в getopts, полягає в тому, що ви вже можете виконати її в bash за допомогою "if-else". Приклад:

if [[ $1 == "" ]]; then
    Your_Usage_Function;
    exit;
else
   #parse options with getopts code block here;
fi

Мати сенс?

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.