Представьте, что у нас есть массив, подобный этому:
declare -a array=( "one" "two" "three" "four" "five" )
for i in "${all[@]}"; do
echo "$i"
done
И мы можем предоставить ввод от пользователя следующим образом:
read -p "Enter a number: " number
Мне нужно кое-что проверить, введен ли пользователь соответствует одному из элементов этого массива. В противном случае это должно быть выполнено:
echo "Try again: "
Этот процесс должен повторяться до тех пор, пока пользовательский ввод не совпадет с одним из элементов массива.
Вы не должны циклично выполняться по массиву, чтобы проверить, принадлежит ли значение ему. Кроме того, в этом случае я использовал бы рекурсивный вызов функции вместо другого цикла. Поскольку я понимаю правильно, что Вы ищете что-то вроде этого:
#!/bin/bash
array=( "one" "two" "three" "four" "five" )
function get_input() {
read -p "${1}: " number
if [[ " ${array[*]} " == *" ${number} "* ]]
then
echo 'true';
else
get_input 'Try again' # a recursive call of the function
fi
}
get_input 'Enter a number' # the initial call of the function
С [[
протестируйте управляют нами иссушающий для точного совпадения ==
между одной строкой (левая сторона) и одним регулярным выражением (правая сторона).
Выражение " ${array[*]} "
развернет наш массив как строку, окруженную двумя пробелами, таким образом каждый элемент (даже первое и последнее) будет окружен пробелами - попытка echo '^'" ${array[*]} "'$'
.
Регулярное выражение *" ${number} "*
будет соответствовать любому, представил в виде строки, которые состоят из значения переменной $number
, окруженный пробелами, окруженными никакой матерью, что другие символы *
.
Мы можем выполнить такой тест некоторыми другими инструментами как grep
(с подавленным stdout -q
, и поиск точного совпадения \<...\>
). Вот одна забавная версия:
#!/bin/bash
array=( "one" "two" "three" "four" "five" )
function get_input() {
read -p "${1}: " nm
echo "${array[*]}" | grep -q "\<${nm}\>" && echo 'true' || get_input 'Try again'
}
get_input "Enter a number"
Если мы хотим назвать соответствующее количество каждого элемента в массиве вместо того, чтобы вставить слова как ''один'' или ''два'', что мы можем сделать? например: Введите номер: 2
#!/bin/bash
array=( "one" "two" "three" "four" "five" )
# Get the lenght of the array
array_lenght="${#array[*]}"
function get_input() {
read -p "${1}: " number
# Test whether the variable $number has a value &and&
# test whether as integer this value is less or equal to the $array_lenght
if [[ ! -z ${number} ]] && (( number <= array_lenght && number > 0 ))
then
# Outpit the value of the cerain array element
# Note the first array element has number 0
echo "${array[$(( number - 1 ))]}"
else
get_input 'Try again'
fi
}
get_input 'Enter an integer number'
Можно превратить массив в ассоциативный массив вместо этого.
#!/bin/bash
declare -A array=([one]=1 [two]=1 [tree]=1 [four]=1 [five]=1)
m="Guess? "
while true; do
read -r -p "$m" i
[[ ${array[$i]} == 1 ]] && break || m="Guess again? "
done
echo "Good guess!"
Вероятно, все другие ответы более эффективны, чем этот, но я думаю, что это более благоприятно для новичка:
declare -a all=( "one" "two" "three" "four" "five" )
read -p "Enter a number: " number
while true; do
for i in "${all[@]}"; do
if [[ "$number" = "$i" ]]; then
exit 0
fi
done
read -p "Try again: " number
done
#!/bin/bash
declare -a array=("one" "two" "three" "four" "five")
number="wrong"
while [[ ! "${array[@]}" =~ "${number}" ]]; do
[[ "${number}" != "wrong" ]] && echo "Incorrect"
read -p "Insert number: " number
done