С помощью:
set -o nounset
Имея индексированный массив, например:
myArray=( "red" "black" "blue" )
Какой самый короткий способ проверить, установлен ли элемент 1?
Иногда использую следующее:test "${#myArray[@]}" -gt "1" && echo "1 exists" || echo "1 doesn't exist"
Я хотел бы знать, есть ли предпочтительный вариант.
Как работать с непоследовательными индексами?
myArray=() myArray[12]="red" myArray[51]="black" myArray[129]="blue"
Как быстро проверить, например, что
51
уже установлено?Как работать с ассоциативными массивами?
declare -A myArray myArray["key1"]="red" myArray["key2"]="black" myArray["key3"]="blue"
Как быстро проверить, например, что
key2
уже используется?
+abc
,[ ${array[key]} ]
будет оцениваться как false, если элемент действительно установлен, но с пустым значением, поэтому фактически проверяется непустота значения, а не наличие ключа.+abc
также не работает, когдаarray[key]
не установлен иset -u
действует.Из 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] - нет.
источник
set -u
, почему[[ -v "${foo[bar]}" ]]
выдает ошибку несвязанной переменной, еслиbar
ее нет в словаре? Прекрасно работает без${}
; Просто привык по умолчанию для всего."${foo[bar]}"
сначала оценивает переменную массива, поэтому[[ -v
команда проверяет переменную с именем этого значенияНовый ответ
Начиная с версии 4.2 трепать(и новее), есть новая
-v
опция встроеннойtest
команды.array=([12]="red" [51]="black" [129]="blue") for i in 10 12 30 {50..52} {128..131};do if [ -v array[i] ];then echo "Variable 'array[$i]' is defined" else echo "Variable 'array[$i]' not exist" fi done Variable 'array[10]' not exist Variable 'array[12]' is defined Variable 'array[30]' not exist Variable 'array[50]' not exist Variable 'array[51]' is defined Variable 'array[52]' not exist Variable 'array[128]' not exist Variable 'array[129]' is defined Variable 'array[130]' not exist Variable 'array[131]' not exist
Это работает с ассоциативными массивами таким же образом:
declare -A aArray=([foo]="bar" [bar]="baz" [baz]=$'Hello world\041') for i in alpha bar baz dummy foo test;do if [ -v aArray[$i] ];then echo "Variable 'aArray[$i]' is defined" else echo "Variable 'aArray[$i]' not exist" fi done Variable 'aArray[alpha]' not exist Variable 'aArray[bar]' is defined Variable 'aArray[baz]' is defined Variable 'aArray[dummy]' not exist Variable 'aArray[foo]' is defined Variable 'aArray[test]' not exist
С небольшой разницей:
в обычных массивах переменная в скобках (
[i]
) является целочисленной, поэтому символ доллара ($
) не требуется, но для ассоциативного массива, поскольку ключ является словом,$
требуется ([$i]
)!Старый ответ для трепать до V4.2
К сожалению, bash никак не влияет на разницу между пустой и неопределенной переменной.
Но есть несколько способов:
$ 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 как в чистом 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
или даже создать новую bash-функцию getIfExist, которая возвращает желаемое значение и выходит с ложным кодом результата, если желаемое значение не существует:
$ 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
источник
bash 4.2.46
. Работает дальшеbash 4.4.12
.-v
вариантtest
илиgetIfExist
функция?-v
Не работает с массивами на моем CentOS 7.7.1908 с Баш 4.2.46. Код из вашего первого блока кодаnot exist
во всех случаях печатается под этим bash. (Также пробовал[$i]
вместо[i]
, без разницы)протестировано в 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
источник
+
расширение параметра, чтобы заменить пустое значение некоторым заполнителем, например подчеркиванием. Напримерdeclare -A a[x]=;[[ ${a[x]} ]];echo $?
печатает1
, аdeclare -A a[x]=;[[ ${a[x]+_} ]];echo $?
печатает0
.А как насчет
-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
источник
Это самый простой способ, который я нашел для скриптов.
<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
источник
Я написал функцию, чтобы проверить, существует ли ключ в массиве в 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)
источник