Відповіді:
У Bash 4 можна використовувати асоціативні масиви:
# set up array of constants
declare -A array
for constant in foo bar baz
do
array[$constant]=1
done
# test for existence
test1="bar"
test2="xyzzy"
if [[ ${array[$test1]} ]]; then echo "Exists"; fi # Exists
if [[ ${array[$test2]} ]]; then echo "Exists"; fi # doesn't
Щоб налаштувати масив спочатку, ви також можете виконати прямі завдання:
array[foo]=1
array[bar]=1
# etc.
або таким чином:
array=([foo]=1 [bar]=1 [baz]=1)
${array[$test1]}
це просто, але є проблема: він не працюватиме, якщо ви використовуєте set -u
в своїх сценаріях (що рекомендується), оскільки ви отримаєте "незв'язану змінну".
Це старе питання, але я думаю , що це найпростіше рішення ще не з'явилося: test ${array[key]+_}
. Приклад:
declare -A xs=([a]=1 [b]="")
test ${xs[a]+_} && echo "a is set"
test ${xs[b]+_} && echo "b is set"
test ${xs[c]+_} && echo "c is set"
Виходи:
a is set
b is set
Щоб побачити, як це працює, перевірте це .
env
щоб уникнути неясностей у псевдонімах, прогах та інших функціях, які, можливо, прийняли назву "тест". Як і вище env test ${xs[a]+_} && echo "a is set"
. Ви також можете отримати цю функціональність, скориставшись подвійними дужками, той самий трюк, як і перевірка нуля:[[ ! -z "${xs[b]+_}" ]] && echo "b is set"
[[ ${xs[b]+set} ]]
Існує спосіб перевірити, чи існує елемент асоціативного масиву (не встановлений), він відрізняється від порожнього:
isNotSet() {
if [[ ! ${!1} && ${!1-_} ]]
then
return 1
fi
}
Потім використовуйте його:
declare -A assoc
KEY="key"
isNotSet assoc[${KEY}]
if [ $? -ne 0 ]
then
echo "${KEY} is not set."
fi
if ! some_check then return 1
= some_check
. Отже: isNotSet() { [[ ... ]] }
. Ознайомтесь із моїм рішенням нижче, це можна зробити простою перевіркою.
Ви можете побачити, чи є запис, перенісши вміст масиву в режим grep.
printf "%s\n" "${mydata[@]}" | grep "^${val}$"
Ви також можете отримати індекс запису з grep -n, який повертає номер рядка відповідності (не забудьте відняти 1 для отримання нульового індексу). Це буде досить швидко, за винятком дуже великих масивів.
# given the following data
mydata=(a b c "hello world")
for val in a c hello "hello world"
do
# get line # of 1st matching entry
ix=$( printf "%s\n" "${mydata[@]}" | grep -n -m 1 "^${val}$" | cut -d ":" -f1 )
if [[ -z $ix ]]
then
echo $val missing
else
# subtract 1. Bash arrays are zero-based, but grep -n returns 1 for 1st line, not 0
echo $val found at $(( ix-1 ))
fi
done
a found at 0
c found at 2
hello missing
hello world found at 3
пояснення:
$( ... )
це те саме, що використовувати задні посилання для збору результатів команди в змінну printf
виводить мій дані по одному елементу на рядок @
замість *.
цього уникає поділу "привіт світу" на 2 рядки)grep
шукає точний рядок: ^
і $
співпадає початок і кінець рядкаgrep -n
повертає рядок № у вигляді 4: привіт світ grep -m 1
знаходить лише перший матчcut
витягує лише номер рядка Можна, звичайно, скласти віднімання в команду. Але потім тестуйте -1 на відсутність:
ix=$(( $( printf "%s\n" "${mydata[@]}" | grep -n -m 1 "^${val}$" | cut -d ":" -f1 ) - 1 ))
if [[ $ix == -1 ]]; then echo missing; else ... fi
$(( ... ))
робить цілу арифметикуЯ не думаю , що ви можете зробити це правильно , без зациклення , якщо ви не дуже обмежених даних в масиві.
Ось один простий варіант, це правильно би сказав, що "Super User"
існує в масиві. Але це також би сказало, що "uper Use"
є в масиві.
MyArray=('Super User' 'Stack Overflow' 'Server Fault' 'Jeff' );
FINDME="Super User"
FOUND=`echo ${MyArray[*]} | grep "$FINDME"`
if [ "${FOUND}" != "" ]; then
echo Array contains: $FINDME
else
echo $FINDME not found
fi
#
# If you where to add anchors < and > to the data it could work
# This would find "Super User" but not "uper Use"
#
MyArray2=('<Super User>' '<Stack Overflow>' '<Server Fault>' '<Jeff>' );
FOUND=`echo ${MyArray2[*]} | grep "<$FINDME>"`
if [ "${FOUND}" != "" ]; then
echo Array contains: $FINDME
else
echo $FINDME not found
fi
Проблема полягає в тому, що немає простого способу додати якорі (що я можу придумати), окрім прокручування масиву. Якщо ви не можете додати їх перед тим, як помістити їх у масив ...
grep "\b$FINDME\b"
). Можливо, це могло б працювати з не алфавітно-цифровими константами, у яких немає пробілів, з "(^| )$FINDME(\$| )"
(або чимось подібним ... я ніколи не зміг дізнатися, який аромат використовує regexp grep.)
#!/bin/bash
function in_array {
ARRAY=$2
for e in ${ARRAY[*]}
do
if [[ "$e" == "$1" ]]
then
return 0
fi
done
return 1
}
my_array=(Drupal Wordpress Joomla)
if in_array "Drupal" "${my_array[*]}"
then
echo "Found"
else
echo "Not found"
fi
in_array
. Ура
${ARRAY[@]}
слід використовувати.