Как мы можем проверить, равен ли пользовательский ввод одному элементу массива?

Представьте, что у нас есть массив, подобный этому:

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: " 

Этот процесс должен повторяться до тех пор, пока пользовательский ввод не совпадет с одним из элементов массива.

4
задан 1 October 2019 в 20:18

4 ответа

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

#!/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'
3
ответ дан 23 October 2019 в 09:42

Можно превратить массив в ассоциативный массив вместо этого.

#!/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!"
5
ответ дан 23 October 2019 в 09:42

Вероятно, все другие ответы более эффективны, чем этот, но я думаю, что это более благоприятно для новичка:

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
3
ответ дан 23 October 2019 в 09:42
#!/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
2
ответ дан 23 October 2019 в 09:42

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

Похожие вопросы: