2012-02-29 2 views
1

Рассмотрим следующий код Баш:Баш - сравнить строку с ключами ассоциативного массива

echo -e "\nThe following versions are available for install:" 
declare -A VERS 
CNT=0 
for FILE in `ls ${ASSET_DIR}/enterprise`; do 
    let "CNT++" 
    VERS_STR=`sed -e 's/^file-\([0-9].[0-9].[0-9]\).zip/\1/' <<< ${FILE}` 
    VERS[${CNT}]=${VER_STR} 
done 
for i in ${!VERS[@]}; do 
    echo " ${i} - ${VERS[${i}]}" 
done 
echo -n "Which version do you want to install?: " 
read VERS_INPUT 

$VERS_INPUT следует приравнивать к одному из ключей в ассоциативном массиве $VERS. Как я могу проверить, что значение $VERS_INPUT равно любому из ключей $VERS. Поскольку это прямо сейчас, с нашей текущей настройкой, есть 6 доступных опций, созданных из циклов for, но у этого есть потенциал для роста, поэтому я не хочу делать это статической проверкой и должен менять сценарий каждый время добавляется дополнительный файл в ${ASSET_DIR}/enterprise. Я предполагаю, что оператор if в порядке, но я не уверен, как бы проверить, соответствует ли он ключу из ассоциативного массива.


РЕДАКТИРОВАТЬ:

В качестве примера, предположим, что первый цикл динамически ассоциативный массив $VERS с четырьмя значениями:

$ echo $ENV["1"] 
3.4.3 

$ echo $ENV["2"] 
3.4.4 

$ echo $ENV["3"] 
3.4.5 

$ echo $ENV["4"] 
3.4.6 

пользователю предлагается, чтобы ввести значение (присвоено переменной $VERS_INPUT), которая, мы надеемся, будет 1, 2, 3 или 4. Как я могу проверить, что значение $VERS_INPUT равно либо 1, 2, 3, либо 4. Очевидно, что это произвольный пример, так как мой список в настоящее время имеет 6 доступных опций и будет только расти дальше. Я хочу сделать это как можно более динамичным, так как 1, 2, 3, 4 и т. Д. ... динамически генерируется из первого цикла for и не генерируется вручную.

+0

Не разбирайте вывод 'ls', если вы можете его избежать. Пробелом является наш враг. Пробелы в именах файлов - это огромный враг. 'для FILE в $ {ASSET_DIR}/enterprise/*; do' должен это делать. Позаботьтесь о скрытых файлах. –

ответ

1

Надеюсь, я понял ваш вопрос: сопоставление ввода пользователя с индексом массива неизвестной длины. Это testcode работы:

#!/bin/bash 
VERS=(1.1.1 1.1.2 1.2.1 1.2.2 1.3.1 terminate) 

select val in ${VERS[*]} 
do 
    case $val in 
     terminate) 
     echo "... done" 
     break 
     ;; 
     [0-9]*) 
     echo "match " $val 
     ;; 
     *) 
     echo "fail (empty:)" $val 
     ;; 
    esac  
done 

интерактивный вывод:

./version.sh 
1) 1.1.1  3) 1.2.1  5) 1.3.1 
2) 1.1.2  4) 1.2.2  6) terminate 
#? 0 
fail (empty:) 
#? 1 
match 1.1.1 
#? 6 
... done 

Если пользователь вводит 1 до 5, связанный с ним элемент массива распечатывается.

Вход заканчивается 6.

Это не совсем то, что вы просили, но это оболочка buildin и, возможно, пригодная для использования. help select печатает главу manpage.

+0

Не совсем. Я отредактировал исходный вопрос с дальнейшим разъяснением, используя произвольный пример. Массив динамически генерируется, и я хочу сравнить строку с ключами в массиве, а не значением, связанным с этими ключами. – Scott

+0

@Scott: Обновлен мой ответ –

+0

Итак, если я не ошибаюсь, оказалось бы, что между 'do' и' done' я могу включить дополнительную проверку, чтобы гарантировать, что строка не пуста и что она соответствует 3-значной шаблон с выражением bash if? Правильно ли я считаю, что это будет приемлемое решение? – Scott

Смежные вопросы