2014-09-23 7 views
2

У меня есть большое количество переменных конфигурации, для которых я хочу, чтобы пользователи выдавали подтверждение значений. Таким образом, может существовать какая-то переменная, указывающая номер запуска, и я хочу, чтобы скрипт спросил у пользователя, соответствует ли текущее значение переменной. Если пользователь отвечает, что значение не в порядке, скрипт запрашивает новое значение и присваивает его переменной.Как написать функцию 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 "--------------------------------------------------------------------------------" 
+0

Этот вопрос не соответствует теме, потому что речь идет о просмотре кода. – chepner

+0

№ Код не работает.Я не уверен, почему и прошу помощи. – d3pd

+0

@chepner: Только часть обзора кода. Существует сообщение об ошибке: «он заглох». – bishop

ответ

4

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

myVariable="$(confirmVariableValue "myVariable")" 

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

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

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

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

Мнение на основе комментариев: Я был бы недоволен таким конфигурационным скриптом. Это слишком болтливо. Для меня лучше:

  • распечатывают описание и значение по умолчанию
  • и спросить 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 "[email protected]" >&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 
+0

О, я не знал о 'printf -v'. Это потрясающе! – bishop

+0

А, это очень изящно. Благодарим вас за четкое объяснение проблемы и решение, которое не только более удобно, но и более эффективно в коде. – d3pd

+0

@ d3pd С большим удовольствием. ;) – jm666

1

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

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

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 использование read -i.

+0

с использованием 'eval', когда пользователь вводит входные данные, может быть немного опасным ... (человеческий фактор, ошибки ...) – jm666

+0

@ jm666: Да. Теперь, когда я знаю о 'printf -v' (спасибо за подсказку!), Я почти полностью уничтожил последнее разумное использование' eval'. – bishop

+0

:) Проверьте также 'declare' (набор). Также позволяет установить переменную. с удовольствием помогли :) – jm666