LINUX.ORG.RU

bash, getopts

 ,


0

2

Если задать для getopts несколько параметров но при вызове пропустить значения, то для для предыдущего параметра значением будет название следующего:

$ cat bin/testbash.sh 
#!/bin/bash
#

aaa=
bbb=
ccc=
ddd=

while getopts ":a:b:c:d:" scriptopt
do
    case "${scriptopt}" in
       a)
           aaa="${OPTARG}"
       ;;
       b)
           bbb="${OPTARG}"
       ;;
       c)
           ccc="${OPTARG}"
       ;;
       d)
           ddd="${OPTARG}"
       ;;
       :)
           echo "Error"
           exit 1
       ;;
    esac
done

echo "
${aaa}
${bbb}
${ccc}
${ddd}
"
$ testbash.sh -a 111 -b 222 -c 333 -d 444

111
222
333
444

$ testbash.sh -a 111 -b 222 -c 
Error
$ testbash.sh -a 111 -b 222 -c -d 

111
222
-d


$ 

В принципе это не смертельно, но может я просто чего не понимаю?

★★★★★

Лютый фейспалм. У тебя идут пары [параметр, значение], ты не «пропустил значение», ты указал значение в виде имени другого параметра.

Если getopts'у сказано, что у параметра должно быть значение, он в качестве значения возьмёт аргумент командной строки, следующий за аргументом-параметром, вне зависимости от его содержимого.

Если хочешь «пропустить», укажи пустую строку:

$ testbash.sh -a 111 -b 222 -c '' -d

tiandrey ★★★★★
()
Последнее исправление: tiandrey (всего исправлений: 3)
Ответ на: комментарий от tiandrey

Ну то есть можно списать на то, что «это же баш..!!11»? А то в питоне например argparse разбирает аргументы нормально.

Я не хочу пропускать, я хочу сообщение об ошибке.

sin_a ★★★★★
() автор топика
Последнее исправление: sin_a (всего исправлений: 1)
Ответ на: комментарий от sin_a

Поведение баша корректное, это в питоне в argparse добавили отдельную проверку, что каждый аргумент-значение не должен начинаться на '-'. Вопрос, нормально ли это, спорный. Читать здесь: https://docs.python.org/dev/library/argparse.html#arguments-containing

Спорный - потому что непонятно, что делать, если я хочу передать именно значение '-d' параметру '-c'.

tiandrey ★★★★★
()
Последнее исправление: tiandrey (всего исправлений: 2)
Ответ на: комментарий от tiandrey

На мой взгляд поведение питона правильное. И именно для последнего случая нужны кавычки.

sin_a ★★★★★
() автор топика
Ответ на: комментарий от tiandrey

Наверно мы не понимаем друг друга. Нет, мне не нужно передать кавычки в качестве параметра.

sin_a ★★★★★
() автор топика
Ответ на: комментарий от tiandrey

Если параметру -с нужно присвоить значение -д то можно использовать кавычки:

$ testbash.sh -a 111 -b 222 -c "-d" 
Кстати, питону кавычки в этом случае не помогают, у него значение начинаться на "-" не может. Наверно это недостаток, хотя мне трудно представить случай когда может понадобиться такой параметр.

sin_a ★★★★★
() автор топика
Ответ на: комментарий от sin_a

Понимаешь ли, дело в том, что эти кавычки не попадут в скрипт. Их обработает и съест тот шелл, который командную строчку обрабатывает, а не тот шелл, который будет скрипт интерпретировать (это два разных процесса, если что).

Кавычки нужны для того, чтобы иметь возможность иметь аргументы командной строки со специальными символами внутри, например, чтобы передать аргумент с пробелом. Ибо аргументы разбиваются именно по whitespace-символам (которые в IFS записаны, по умолчанию это пробел, табуляция и перевод строки). В данном случае эти кавычки бессмысленны, потому что аргумент внутри них никаких спецсимволов не содержит.

tiandrey ★★★★★
()
Ответ на: комментарий от tiandrey

Вообще, мне сама необходимость параметров типа "-д" кажется несколько надуманной. А мой вопрос — это как раз вопрос возможной ошибки. Если скрипт вызывает не человек, то параметры вполне могут пойти пустыми.

sin_a ★★★★★
() автор топика
Ответ на: комментарий от sin_a

Да нет, простейший юзкейс - когда ты запускаешь программу, которая будет запускать другую программу, и ты первой программе хочешь передать аргумент, с которым она будет запускать вторую программу.

Если ты будешь свой скрипт из другого скрипта дёргать, передавай параметр в кавычках. Тогда даже если он будет пустой, он передастся как пустая строка.

Хочешь поведение, как в питоне - проверяй, что значение каждого параметра не начинается на '-':

#!/bin/bash

aaa=
bbb=
ccc=
ddd=

while getopts ":a:b:c:d:" scriptopt
do
    if [ "$(echo "x${OPTARG}" | cut -c 1-2)" = "x-" ]; then
        echo "Error"
        exit 1
    fi
    case "${scriptopt}" in
       a)
           aaa="${OPTARG}"
       ;;
       b)
           bbb="${OPTARG}"
       ;;
       c)
           ccc="${OPTARG}"
       ;;
       d)
           ddd="${OPTARG}"
       ;;
       :)
           echo "Error"
           exit 1
       ;;
    esac
done

echo "
${aaa}
${bbb}
${ccc}
${ddd}
"

tiandrey ★★★★★
()
Последнее исправление: tiandrey (всего исправлений: 1)

bash ведёт себя как раз правильно, как и многие остальные утилиты. А вот в питоне поведение нелогичное.

Пара примеров:

└─> du -d 1 -h
4,0K    .
└─> du -d -h
du: недопустимая максимальная глубина «-h»
По команде «du --help» можно получить дополнительную информацию.
└─> mkdir -m a=rwx test
└─> ls
test
└─> mkdir -m test
mkdir: пропущен операнд
По команде «mkdir --help» можно получить дополнительную информацию.
└─> wget -O lor.html -q http://linux.org.ru
└─> ls
lor.html
└─> wget -O -q http://linux.org.ru
--2016-07-07 23:33:45--  http://linux.org.ru/
Распознаётся linux.org.ru… 178.248.233.6
Подключение к linux.org.ru|178.248.233.6|:80... соединение установлено.
HTTP-запрос отправлен. Ожидание ответа… 302 Moved Temporarily
Адрес: http://www.linux.org.ru/ [переход]
--2016-07-07 23:33:45--  http://www.linux.org.ru/
Распознаётся www.linux.org.ru… 178.248.233.6
Повторное использование соединения с linux.org.ru:80.
HTTP-запрос отправлен. Ожидание ответа… 200 OK
Длина: нет данных [text/html]
Сохранение в: «-q»

-q                                                     [<=>]  59,38K  --.-KB/s    in 0,09s   

2016-07-07 23:33:46 (634 KB/s) - «-q» сохранён [60800]

└─> ls
lor.html  -q

shell-script ★★★★★
()
Ответ на: комментарий от shell-script

Ну вот не могу себе представить что кому нибудь понадобился файл "-q". Хотя это вопрос точки зрения программиста. А проверить на стандартных утилитах я, да, поленился...

sin_a ★★★★★
() автор топика
Ответ на: комментарий от tiandrey

Можно и так. Хотя я в текущем случае пожалуй просто устрою тупую проверку двум параметрам.

А если бы я передавал параметры то предпочёл бы набор ключей. Да, это менее гибко, но я перестраховщик. И здесь у меня обёртка между чужими другими инструментами, поэтому условия, кавычки или какие ещё, не мои.

sin_a ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.