Usando:
set -o nounset
Ter uma matriz indexada como:
myArray=( "red" "black" "blue" )
Qual é o caminho mais curto para verificar se o elemento 1 está definido?
Às vezes uso o seguinte:test "${#myArray[@]}" -gt "1" && echo "1 exists" || echo "1 doesn't exist"
Gostaria de saber se existe um preferido.
Como lidar com índices não consecutivos?
myArray=() myArray[12]="red" myArray[51]="black" myArray[129]="blue"
Como verificar rapidamente o que
51
já está definido, por exemplo?Como lidar com matrizes associativas?
declare -A myArray myArray["key1"]="red" myArray["key2"]="black" myArray["key3"]="blue"
Como verificar rapidamente o que
key2
já é usado por exemplo?
+abc
,[ ${array[key]} ]
será avaliado como falso se o elemento estiver realmente definido, mas com um valor vazio, então ele está realmente testando o valor não vazio em vez da existência da chave.+abc
também falhou quandoarray[key]
não está definido eset -u
está em vigor.Do man bash , expressões condicionais:
-v varname True if the shell variable varname is set (has been assigned a value).
exemplo:
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
Isso mostrará que ambos foo [bar] e foo [baz] estão configurados (embora o último esteja configurado com um valor vazio) e foo [quux] não.
fonte
set -u
, por que[[ -v "${foo[bar]}" ]]
produz um erro de variável não associada sebar
não existe no dicionário? Funciona bem sem o${}
; Estou acostumado a usá-lo para tudo por padrão."${foo[bar]}"
avalia a variável de matriz primeiro, então o[[ -v
comando testa uma variável com o nome desse valorNova resposta
Da versão 4.2 de bash(e mais recentes), há uma nova
-v
opção detest
comando embutido .A partir da versão 4.3, este teste pode endereçar elementos de arrays.
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
Isso funciona com matrizes associativas da mesma maneira:
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
Com uma pequena diferença:
em arrays regulares, a variável entre colchetes (
[i]
) é inteira, então o símbolo de dólar ($
) não é necessário, mas para array associativo, como a chave é uma palavra,$
é necessário ([$i]
)!Resposta antiga para bash antes de V4.2
Infelizmente, o bash não faz diferença entre uma variável vazia e uma indefinida .
Mas existem algumas maneiras:
$ 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
(não responda)
E para matriz associativa, você pode usar o mesmo:
$ 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
Você poderia fazer o trabalho sem a necessidade de ferramentas externas (sem printf | grep como bash puro ) e, por que não, construir checkIfExist () como uma nova função 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
ou até mesmo criar uma nova função bash getIfExist que retorna o valor desejado e sai com um código de resultado falso se o valor desejado não existir:
$ 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
fonte
bash 4.2.46
. Funcionabash 4.4.12
.-v
opção detest
ougetIfExist
função?-v
foi adicionado ao bash-4.2 MAS o suporte para verificação de índices de array não foi adicionado até o bash-4.3.testado em 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
fonte
+
expansão do parâmetro para substituir um valor vazio por algum espaço reservado, como um sublinhado. Por exemplo ,declare -A a[x]=;[[ ${a[x]} ]];echo $?
imprime1
, masdeclare -A a[x]=;[[ ${a[x]+_} ]];echo $?
imprime0
.Que tal um
-z
teste e o:-
operador?Por exemplo, este script:
#!/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
Impressões:
ABC is set DEF is set
fonte
Esta é a maneira mais fácil que encontrei para scripts.
<search>
é a string que você deseja encontrar,ASSOC_ARRAY
o nome da variável que contém sua matriz associativa.Depende do que você deseja alcançar:
chave existe :
if grep -qe "<search>" <(echo "${!ASSOC_ARRAY[@]}"); then echo key is present; fi
a chave não existe :
if ! grep -qe "<search>" <(echo "${!ASSOC_ARRAY[@]}"); then echo key not present; fi
valor existe :
if grep -qe "<search>" <(echo "${ASSOC_ARRAY[@]}"); then echo value is present; fi
valor existe não :
if ! grep -qe "<search>" <(echo "${ASSOC_ARRAY[@]}"); then echo value not present; fi
fonte
Escrevi uma função para verificar se existe uma chave em uma matriz no 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 }
Exemplo
declare -A my_array my_array['foo']="bar" if [[ "$(array_key_exists 'my_array' 'foo'; echo $?)" = "0" ]]; then echo "OK" else echo "ERROR" fi
Testado com GNU bash, versão 4.1.5 (1) -release (i486-pc-linux-gnu)
fonte