Самый простой способ проверить индекс или ключ в массиве?
С помощью:
set -o nounset
1) Наличие индексированного массива, такого как:
myArray=( "red" "black" "blue" )
Какой самый короткий способ проверить, установлен ли элемент 1?
Я иногда использую следующее:
test "${#myArray[@]}" -gt "1" && echo "1 exists" || echo "1 doesn't exist"
Я хотел бы знать, есть ли предпочтительный.
2) Как бороться с непоследовательными индексами?
myArray=()
myArray[12]="red"
myArray[51]="black"
myArray[129]="blue"
Как быстро проверить, что "51" уже установлен, например?
3) Как бороться с ассоциативными массивами?
declare -A myArray
myArray["key1"]="red"
myArray["key2"]="black"
myArray["key3"]="blue"
Как быстро проверить, что "key2" уже используется, например?
Спасибо
РЕДАКТИРОВАНИЕ
Мне кажется, самый простой способ:
if test "${myArray['key_or_index']+isset}"
then
echo "yes"
else
echo "no"
fi;
Это работает как для индексированных, так и для ассоциативных массивов. Ошибки не отображаются с установленным -o существительным.
Благодаря DoubleDown за заголовок.
Ответы
Ответ 1
Чтобы проверить, установлен ли элемент (применяется как к индексированному, так и ассоциативному массиву)
[ ${array[key]+abc} ] && echo "exists"
В принципе, что ${array[key]+abc}
есть
- Если
array[key]
установлено, верните abc
- Если
array[key]
не задано, не возвращайте ничего
Ссылки:
Функция обертки:
exists(){
if [ "$2" != in ]; then
echo "Incorrect usage."
echo "Correct usage: exists {key} in {array}"
return
fi
eval '[ ${'$3'[$1]+muahaha} ]'
}
Например
if ! exists key in array; then echo "No such array element"; fi
Ответ 2
От man bash, условные выражения:
-v varname
True if the shell variable varname is set (has been assigned a value).
пример:
declare -A foo
foo[bar]="this is bar"
foo[baz]=""
if [[ -v "foo[bar]" ]] ; then
echo "foo[bar] is set"
fi
if [[ -v "foo[baz]" ]] ; then
echo "foo[baz] is set"
fi
if [[ -v "foo[quux]" ]] ; then
echo "foo[quux] is set"
fi
Это покажет, что foo [bar] и foo [baz] установлены (даже если для последнего установлено пустое значение), а foo [quux] нет.
Ответ 3
К сожалению, bash не дает возможности разбить betwen на пустую и undefined переменную.
Но есть несколько способов:
$ array=()
$ array[12]="red"
$ array[51]="black"
$ array[129]="blue"
$ echo ${array[@]}
red black blue
$ echo ${!array[@]}
12 51 129
$ echo "${#array[@]}"
3
$ printf "%s\n" ${!array[@]}|grep -q ^51$ && echo 51 exist
51 exist
$ printf "%s\n" ${!array[@]}|grep -q ^52$ && echo 52 exist
(не отвечайте)
И для ассоциативного массива вы можете использовать то же самое:
$ unset array
$ declare -A array
$ array["key1"]="red"
$ array["key2"]="black"
$ array["key3"]="blue"
$ echo ${array[@]}
blue black red
$ echo ${!array[@]}
key3 key2 key1
$ echo ${#array[@]}
3
$ set | grep ^array=
array=([key3]="blue" [key2]="black" [key1]="red" )
$ printf "%s\n" ${!array[@]}|grep -q ^key2$ && echo key2 exist || echo key2 not exist
key2 exist
$ printf "%s\n" ${!array[@]}|grep -q ^key5$ && echo key5 exist || echo key5 not exist
key5 not exist
Вы можете выполнить эту работу без использования внешних инструментов (нет printf | grep as pure bash), а почему бы и нет, построить checkIfExist() в качестве новой функции bash:
$ checkIfExist() {
eval 'local keys=${!'$1'[@]}';
eval "case '$2' in
${keys// /|}) return 0 ;;
* ) return 1 ;;
esac";
}
$ checkIfExist array key2 && echo exist || echo don\'t
exist
$ checkIfExist array key5 && echo exist || echo don\'t
don't
или даже создать новую функцию getIfExist bash, которая возвращает желаемое значение и выйдет с ложным результатом-кодом, если желаемое значение не существует:
$ getIfExist() {
eval 'local keys=${!'$1'[@]}';
eval "case '$2' in
${keys// /|}) echo \${$1[$2]};return 0 ;;
* ) return 1 ;;
esac";
}
$ getIfExist array key1
red
$ echo $?
0
$ # now with an empty defined value
$ array["key4"]=""
$ getIfExist array key4
$ echo $?
0
$ getIfExist array key5
$ echo $?
1
Ответ 4
проверено в bash 4.3.39 (1) -release
declare -A fmap
fmap['foo']="boo"
key='foo'
# should echo foo is set to 'boo'
if [[ -z "${fmap[${key}]}" ]]; then echo "$key is unset in fmap"; else echo "${key} is set to '${fmap[${key}]}'"; fi
key='blah'
# should echo blah is unset in fmap
if [[ -z "${fmap[${key}]}" ]]; then echo "$key is unset in fmap"; else echo "${key} is set to '${fmap[${key}]}'"; fi
Ответ 5
Это самый простой способ, который я нашел для скриптов.
<search>
- это строка, которую вы хотите найти, ASSOC_ARRAY
имя переменной, содержащей ваш ассоциативный массив.
Зависит от того, чего вы хотите достичь:
существует:
if grep -qe "<search>" <(echo "${!ASSOC_ARRAY[@]}"); then echo key is present; fi
ключ отсутствует:
if ! grep -qe "<search>" <(echo "${!ASSOC_ARRAY[@]}"); then echo key not present; fi
:
if grep -qe "<search>" <(echo "${ASSOC_ARRAY[@]}"); then echo value is present; fi
значение не существует:
if ! grep -qe "<search>" <(echo "${ASSOC_ARRAY[@]}"); then echo value not present; fi
Ответ 6
Я написал функцию, чтобы проверить, существует ли ключ в массиве в Bash:
# Check if array key exists
# Usage: array_key_exists $array_name $key
# Returns: 0 = key exists, 1 = key does NOT exist
function array_key_exists() {
local _array_name="$1"
local _key="$2"
local _cmd='echo ${!'$_array_name'[@]}'
local _array_keys=($(eval $_cmd))
local _key_exists=$(echo " ${_array_keys[@]} " | grep " $_key " &>/dev/null; echo $?)
[[ "$_key_exists" = "0" ]] && return 0 || return 1
}
Пример
declare -A my_array
my_array['foo']="bar"
if [[ "$(array_key_exists 'my_array' 'foo'; echo $?)" = "0" ]]; then
echo "OK"
else
echo "ERROR"
fi
Протестировано с помощью GNU bash, версия 4.1.5 (1) -release (i486-pc-linux-gnu)
Ответ 7
Как насчет теста -z
и оператора :-
?
Например, этот скрипт:
#!/usr/bin/env bash
set -e
set -u
declare -A sample
sample["ABC"]=2
sample["DEF"]=3
if [[ ! -z "${sample['ABC']:-}" ]]; then
echo "ABC is set"
fi
if [[ ! -z "${sample['DEF']:-}" ]]; then
echo "DEF is set"
fi
if [[ ! -z "${sample['GHI']:-}" ]]; then
echo "GHI is set"
fi
Печать:
ABC is set
DEF is set