Как написать функцию Bash, которая подтверждает значение существующей переменной с пользователем

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

Я сделал начальную попытку для функции для этого, но есть некоторые трудности с ее выполнением; это глохнет. Я был бы признателен за помощь в решении проблемы, а также за любую критику подхода, который я использую. Код выглядит следующим образом:

confirmVariableValue(){
    variableName="${1}"
    variableValue="${!variableName}"
    while [[ "${userInput}" != "n" && "${userInput}" != "y" ]]; do
        echo "variable "${variableName}" value: "${variableValue}""
        echo "Is this correct? (y: continue / n: change it / other: exit)"
        read userInput
        # Make the user input lowercase.
        userInput="$(echo "${userInput}" | sed 's/\(.*\)/\L\1/')"
        # If the user input is "n", request a new value for the variable. If the
        # user input is anything other than "y" or "n", exit. If the user input
        # is "y", then the user confirmation loop ends.
        if [[ "${userInput}" == "n" ]]; then
            echo "enter variable "${variableName}" value:"
            read variableValue
        elif [[ "${userInput}" != "y" && "${userInput}" != "n" ]]; then
            echo "terminating"
            exit 0
        fi
    done
    echo "${variableValue}"
}

myVariable="run_2014-09-23T1909"
echo "--------------------------------------------------------------------------------"
echo "initial variable value: "${myVariable}""
myVariable="$(confirmVariableValue "myVariable")"
echo "final variable value: "${myVariable}""
echo "--------------------------------------------------------------------------------"

2 ответа

Решение

Проблема здесь:

myVariable="$(confirmVariableValue "myVariable")"

ваши вопросы, как

    echo "Is this correct? (y: continue / n: change it / other: exit)"

собираются в myVariable а не на экран.

Попробуйте напечатать вопросы в STDERR или любой другой дескриптор файла, кроме STDOUT.

Комментарий, основанный на мнении: я был бы недоволен таким config-скриптом. Это слишком болтливый. Для меня лучше

  • распечатать описание и значение по умолчанию
  • и попросить Press Enter for confirm or enter a new value or <something> for exit>

Вы также можете использовать следующую технику:

  • использовать удар readline библиотека для read команда с -e
  • использовать -i value для установки значения по умолчанию для редактирования
  • использовать printf -v variable печатать в переменную, поэтому вам не нужно использовать var=$(...) ни какой (потенциально) опасный eval...

пример:

err() { echo "$@" >&2; return 1; }

getval() {
    while :
    do
        read -e -i "${!1}" -p "$1>" inp
        case "$inp" in
            Q|q) err "Quitting...." || return 1 ;;
            "") err "Must enter some value" ;;
            *)
                #validate the input here

                #and print the new value into the variable
                printf -v "$1" "%s" "$inp"
                return 0
                ;;
        esac
    done
}

somevariable=val1
anotherone=val2
x=val3

for var in somevariable anotherone x
do
    getval "$var" || exit 
    echo "new value for $var is: =${!var}="
done

Я не хотел бы, чтобы они ответили "Да", а затем введите новое значение. Просто попросите их ввести новое значение, если хотите, или оставьте поле пустым, чтобы принять значение по умолчанию.

Эта маленькая функция позволяет вам установить несколько переменных за один вызов:

function confirm() {
    echo "Confirming values for several variables."

    for var; do
        read -p "$var = ${!var} ... leave blank to accept or enter a new value: "
        case $REPLY in
        "") # empty use default
            ;;
        *) # not empty, set the variable using printf -v
            printf -v "$var" "$REPLY"
            ;;
        esac
    done
}

Используется так:

$ foo='foo_default_value'
$ bar='default_for_bar'
$ confirm foo bar
Confirming values for several variables.

foo = foo_default_value ... leave blank to accept or enter a new value: bar
bar = default_for_bar ... leave blank to accept or enter a new value:

foo=[bar], bar=[default_for_bar]

Конечно, если пустым может быть значение по умолчанию, то вам необходимо учитывать это, например, @jm666 use of read -i,

Другие вопросы по тегам