#arrays #bash #validation
#массивы #bash #проверка
Вопрос:
Bash 4 в Linux ~
У меня есть массив возможных значений. Я должен ограничить пользовательский ввод этими значениями.
Arr=(hello kitty goodbye quick fox)
Пользователь предоставляет значение в качестве аргумента скрипту:
bash myscript.sh -b var
В настоящее время я пытаюсь выполнить следующее:
function func_exists () {
_var="$1"
for i in ${Arr[@]}
do
if [ "$i" == "$_var" ]
then
echo hooray for "$_var"
return 1
fi
done
return 0
}
func_exists $var
if [ $? -ne 1 ];then
echo "Not a permitted value."
func_help
exit $E_OPTERROR
fi
Кажется, работает нормально, есть ли лучшие методы для проверки пользовательского ввода на соответствие массиву разрешенных значений?
ОБНОВЛЕНИЕ: Мне нравится ответ Джона К…может кто-нибудь разъяснить использование $ @? Я понимаю, что это представляет все позиционные параметры — поэтому мы удаляем первый параметр из стека, а $ @ теперь представляет все остальные параметры, являющиеся переданным массивом … это правильно? Я ненавижу слепо использовать код без понимания…даже если это сработает!
Ответ №1:
Ваше решение — это то, что я бы сделал. Возможно, используя еще несколько оболочек, таких как возврат 0 для успеха и не-0 для сбоя, как это обычно делают команды UNIX.
# Tests if $1 is in the array ($2 $3 $4 ...).
is_in() {
value=$1
shift
for i in "$@"; do
[[ $i == $value ]] amp;amp; return 0
done
return 1
}
if ! is_in "$var" "${Arr[@]}"; then
echo "Not a permitted value." >amp;2
func_help
exit $E_OPTERROR
fi
Тщательное использование двойных кавычек гарантирует, что это сработает, даже если отдельные записи массива содержат пробелы, что разрешено. Это массив из двух элементов: list=('hello world' 'foo bar')
.
Комментарии:
1. Приятные улучшения! Спасибо! За исключением дальнейшего совершенствования, это получит мой голос.
2. Мое понимание значения $ @ в вашей функции: переместите первый аргумент из стека — $ @ теперь представляет остаток. Правильно ли это?
Ответ №2:
Другое решение. is_in — это просто переменная:
Arr=(hello kitty goodbye quick fox)
var='quick'
string=" ${Arr[*]} " # array to string, framed with blanks
is_in=1 # false
# try to delete the variable inside the string; true if length differ
[ "$string" != "${string/ ${var} /}" ] amp;amp; is_in=0
echo -e "$is_in"
Комментарии:
1. Отличное решение. Спасибо! Я оставлю это на потом.
Ответ №3:
function func_exists () {
case "$1"
in
hello)
kitty)
goodbye)
quick)
fox)
return 1;;
*)
return 0;;
esac
}
Комментарии:
1. Проголосовавшему против: извините, вы видели мой ответ в тот момент, когда я случайно отправил его из-за нажатия неправильной клавиши.
![]()
2. Это хорошее решение, но я не уверен, насколько оно было бы читабельным, если бы допустимый входной массив содержал 50-100 элементов.
3. Также можно было бы компактно записать ее в одном случае как
hello|kitty|goodbye|quick|fox)
.4. Я думаю, что для универсальности и удобочитаемости подойдет массив, извлеченный из файла. Не уверен, что это самый эффективный способ проверить входные данные в таком массиве. Решение должно быть способно эффективно и доступно для чтения обрабатывать массивы с более чем 50 элементами.
5. Еще одно преимущество отдельно определенного массива заключается в том, что вы можете передать массив с переменной для тестирования и иметь функцию повторного использования.