Почему нельзя присвоить значение с помощью getopt?

Вопрос или проблема

Вот мой test.sh:

#!/usr/bin/env bash
arg="default"
TEMP=$(getopt --long been: -n 'test.sh' -- "$@")
eval set -- "$TEMP"
while true ; do
    case "$1" in
        --been)
            echo 'в опции been'
            arg="$2"
            shift;;
        --)
            echo 'в конце' 
            shift ; break ;;
    esac
done
echo "$arg"

Присвойте значение arg:

bash  ./test.sh  --been=xxyyzz
в конце
default

Почему не получается получить результат>?

bash  ./test.sh  --been=xxxx
в опции been
xxxx

В manpage для getopt(1) упоминается, в разделе BUGS,

Синтаксис, если вы не хотите никаких коротких переменных опций, не очень интуитивен (вам нужно явно установить их в пустую строку).

Поэтому вам нужно

getopt --long been: -n test.sh "" "$@"

(Если вы хотите включить -- в аргументы getopt, он должен быть до этого пустого аргумента)

С этим изменением,

в опции been
xxyyzz

(Вам также нужен break в секции case для --been, и нужно использовать shift 2, чтобы избавиться от аргумента)

.

Ответ или решение

Ваша проблема с присвоением значения переменной при использовании команды getopt в Bash является распространенной ошибкой, связанной с неверным использованием этой команды и её параметров. Давайте разберем, что происходит и как это исправить.

Объяснение проблемы

В вашей скрипт test.sh, вы определяете переменную arg со значением "default", но не получаете ожидаемого результата при вызове скрипта через bash ./test.sh --been=xxyyzz. Суть проблемы заключается в следующем:

  1. Синтаксис команды getopt: Ваша текущая команда getopt --long been: -n 'test.sh' -- "$@" неправильно обрабатывает аргументы, поскольку нет явного указания на отсутствие коротких опций. getopt ожидает, что все аргументы будут соответствовать его формату.

  2. Отсутствие аргумента: Когда вы вызываете getopt, значения после --been (например, xxyyzz) считаются отдельными аргументами, но так как вы не указали пустую строку как первый аргумент в getopt, это приводит к тому, что значение не передается должным образом.

Решение проблемы

Чтобы исправить вашу ошибку, вы должны внести следующие изменения:

  1. Добавьте пустой аргумент: Измените вызов getopt, добавив пустую строку перед "$@":

    TEMP=$(getopt --long been: -n 'test.sh' "" -- "$@")
  2. Используйте shift 2: После того как вы указали arg="$2" внутри блока case для --been, добавьте shift 2 вместо shift, чтобы сдвинуть на два аргумента (ключ и значение):

    case "$1" in
       --been)
           echo 'in been option'
           arg="$2"
           shift 2;;
  3. Разместите break: Убедитесь, что break находится после shift в блоке case, чтобы корректно завершить цикл после обработки параметров.

Полный исправленный скрипт

Теперь ваш скрипт будет выглядеть следующим образом:

#!/usr/bin/env bash
arg="default"
TEMP=$(getopt --long been: -n 'test.sh' "" -- "$@")
eval set -- "$TEMP"
while true ; do
    case "$1" in
        --been)
            echo 'in been option'
            arg="$2"
            shift 2;;
        --)
            echo 'in the end'
            shift; break;;
    esac
done
echo "$arg"

Проверка скрипта

Теперь, если вы выполните:

bash ./test.sh --been=xxyyzz

Ожидаемый вывод будет:

in been option
xxyyzz

Заключение

Ваша проблема возникла из-за неправильного использования параметров в команде getopt, что привело к неправильной интерпретации ваших аргументов. После исправлений скрипт будет работать корректно, и вы сможете успешно присваивать значения переменным. Если у вас возникнут дополнительные вопросы по использованию getopt, не стесняйтесь спрашивать.

Оцените материал
Добавить комментарий

Капча загружается...