Utilizando:
set -o nounset
Tener una matriz indexada como:
myArray=( "red" "black" "blue" )
¿Cuál es la forma más corta de comprobar si el elemento 1 está configurado?
A veces utilizo lo siguiente:test "${#myArray[@]}" -gt "1" && echo "1 exists" || echo "1 doesn't exist"
Me gustaría saber si hay alguno preferido.
¿Cómo lidiar con índices no consecutivos?
myArray=() myArray[12]="red" myArray[51]="black" myArray[129]="blue"
¿Cómo comprobar rápidamente que
51
ya está configurado, por ejemplo?¿Cómo lidiar con matrices asociativas?
declare -A myArray myArray["key1"]="red" myArray["key2"]="black" myArray["key3"]="blue"
¿Cómo comprobar rápidamente que
key2
ya se utiliza por ejemplo?
+abc
,[ ${array[key]} ]
se evaluará como falso si el elemento está realmente configurado, pero con un valor vacío, por lo que en realidad está probando el valor no vacío en lugar de la existencia de la clave.+abc
también falló cuandoarray[key]
no está configurado yset -u
es efectivo.De man bash , expresiones condicionales:
-v varname True if the shell variable varname is set (has been assigned a value).
ejemplo:
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
Esto mostrará que tanto foo [bar] como foo [baz] están configurados (aunque este último esté configurado en un valor vacío) y foo [quux] no.
fuente
set -u
, ¿por qué[[ -v "${foo[bar]}" ]]
produce un error de variable independiente sibar
no existe en el diccionario? Funciona bien sin el${}
; Estoy acostumbrado a usarlo para todo por defecto."${foo[bar]}"
evalúa primero la variable de matriz, por lo que el[[ -v
comando prueba una variable con el nombre de ese valorNueva respuesta
Desde la versión 4.2 de intento(y más reciente), hay una nueva
-v
opción para eltest
comando incorporado .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
Esto funciona con matrices asociativas de la misma manera:
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
Con una pequeña diferencia:
en las matrices regulares, la variable entre corchetes (
[i]
) es un número entero, por$
lo que no se requiere el símbolo de dólar ( ), pero para la matriz asociativa, ya que la clave es una palabra,$
se requiere ([$i]
).Antigua respuesta para intento antes de V4.2
Desafortunadamente, bash no da forma de diferenciar entre variable vacía e indefinida .
Pero hay algunas formas:
$ 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
(no dar respuesta)
Y para la matriz asociativa, podría usar lo mismo:
$ 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
Puede hacer el trabajo sin la necesidad de herramientas externas (sin printf | grep como bash puro ) y, por qué no, construir checkIfExist () como una nueva función de 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
o incluso crear una nueva función bash getIfExist que devuelva el valor deseado y salga con un código de resultado falso si el valor deseado no existe:
$ 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
fuente
bash 4.2.46
. Funcionabash 4.4.12
.-v
opcióntest
ogetIfExist
función?-v
no funciona en matrices en mis CentOS 7.7.1908 con la fiesta de 02/04/46. El código de su primer bloque de código se imprimenot exist
en todos los casos bajo ese bash. (También probado en[$i]
lugar de[i]
, sin diferencia)probado en 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
fuente
+
expansión de parámetros para reemplazar un valor vacío con un marcador de posición como un guión bajo. Por ejemplo ,declare -A a[x]=;[[ ${a[x]} ]];echo $?
imprime1
, perodeclare -A a[x]=;[[ ${a[x]+_} ]];echo $?
imprime0
.¿Qué pasa con una
-z
prueba y el:-
operador?Por ejemplo, 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
Huellas dactilares:
ABC is set DEF is set
fuente
Esta es la forma más fácil que encontré para scripts.
<search>
es la cadena que desea encontrar,ASSOC_ARRAY
el nombre de la variable que contiene su matriz asociativa.Depende de lo que quieras lograr:
existe la clave :
if grep -qe "<search>" <(echo "${!ASSOC_ARRAY[@]}"); then echo key is present; fi
la clave no existe :
if ! grep -qe "<search>" <(echo "${!ASSOC_ARRAY[@]}"); then echo key not present; fi
existe valor :
if grep -qe "<search>" <(echo "${ASSOC_ARRAY[@]}"); then echo value is present; fi
el valor no existe :
if ! grep -qe "<search>" <(echo "${ASSOC_ARRAY[@]}"); then echo value not present; fi
fuente
Escribí una función para verificar si existe una clave en una matriz en 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 }
Ejemplo
declare -A my_array my_array['foo']="bar" if [[ "$(array_key_exists 'my_array' 'foo'; echo $?)" = "0" ]]; then echo "OK" else echo "ERROR" fi
Probado con GNU bash, versión 4.1.5 (1) -release (i486-pc-linux-gnu)
fuente