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
51ya 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
key2ya 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.+abctambién falló cuandoarray[key]no está configurado yset -ues 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" fiEsto 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 sibarno 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[[ -vcomando 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
-vopción para eltestcomando 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 existEsto 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 existCon 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 existPuede 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'to 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 $? 1fuente
bash 4.2.46. Funcionabash 4.4.12.-vopcióntestogetIfExistfunción?-vno 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 existen 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}]}'"; fifuente
+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
-zprueba 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" fiHuellas dactilares:
ABC is set DEF is setfuente
Esta es la forma más fácil que encontré para scripts.
<search>es la cadena que desea encontrar,ASSOC_ARRAYel 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; fila clave no existe :
if ! grep -qe "<search>" <(echo "${!ASSOC_ARRAY[@]}"); then echo key not present; fiexiste valor :
if grep -qe "<search>" <(echo "${ASSOC_ARRAY[@]}"); then echo value is present; fiel valor no existe :
if ! grep -qe "<search>" <(echo "${ASSOC_ARRAY[@]}"); then echo value not present; fifuente
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" fiProbado con GNU bash, versión 4.1.5 (1) -release (i486-pc-linux-gnu)
fuente