Za pomocą:
set -o nounset
Posiadanie tablicy indeksowanej, takiej jak:
myArray=( "red" "black" "blue" )
Jaki jest najkrótszy sposób sprawdzenia, czy element 1 jest ustawiony?
Czasami używam następujących:test "${#myArray[@]}" -gt "1" && echo "1 exists" || echo "1 doesn't exist"
Chciałbym wiedzieć, czy istnieje preferowany.
Jak radzić sobie z indeksami nieciągłymi?
myArray=() myArray[12]="red" myArray[51]="black" myArray[129]="blue"
Jak na przykład szybko sprawdzić, czy
51
jest już ustawione?Jak radzić sobie z tablicami asocjacyjnymi?
declare -A myArray myArray["key1"]="red" myArray["key2"]="black" myArray["key3"]="blue"
Jak na przykład szybko sprawdzić, co
key2
jest już używane?
+abc
,[ ${array[key]} ]
oceni jako false, jeśli element jest rzeczywiście ustawiony, ale ma wartość pustą, więc w rzeczywistości testuje wartość nie-pustkę, a nie istnienie klucza.+abc
również nie powiodło się, gdyarray[key]
nie jest ustawione iset -u
jest skuteczne.Od man bash , wyrażenia warunkowe:
-v varname True if the shell variable varname is set (has been assigned a value).
przykład:
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
To pokaże, że zarówno foo [bar], jak i foo [baz] są ustawione (nawet jeśli ta ostatnia ma wartość pustą), a foo [quux] nie.
źródło
set -u
, dlaczego[[ -v "${foo[bar]}" ]]
generuje niepowiązany błąd zmiennej, jeślibar
nie istnieje w słowniku? Działa dobrze bez${}
; Po prostu używam go domyślnie do wszystkiego."${foo[bar]}"
najpierw ocenia zmienną tablicową, więc[[ -v
polecenie sprawdza zmienną o nazwie tej wartościNowa odpowiedź
Od wersji 4.2 grzmotnąć(i nowsze), dostępna jest nowa
-v
opcja wbudowanegotest
polecenia.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
To działa z tablicami asocjacyjnymi w ten sam sposób:
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
Z małą różnicą: w
zwykłych tablicach zmienna w nawiasach kwadratowych (
[i]
) jest liczbą całkowitą, więc symbol dolara ($
) nie jest wymagany, ale w przypadku tablicy asocjacyjnej, ponieważ klucz jest słowem,$
jest wymagany ([$i]
)!Stara odpowiedź na grzmotnąć przed V4.2
Niestety, bash nie daje żadnej możliwości zrobienia różnicy między pustą a niezdefiniowaną zmienną.
Ale jest kilka sposobów:
$ 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
(nie dawaj odpowiedzi)
A dla tablicy asocjacyjnej możesz użyć tego samego:
$ 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
Możesz wykonać to zadanie bez konieczności używania zewnętrznych narzędzi (bez printf | grep jako czystego bash ) i dlaczego nie, zbuduj checkIfExist () jako nową funkcję basha:
$ 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
lub nawet utwórz nową funkcję bash getIfExist, która zwraca żądaną wartość i kończy pracę z fałszywym kodem wyniku, jeśli żądana wartość nie istnieje:
$ 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
źródło
bash 4.2.46
. Działa dalejbash 4.4.12
.-v
opcjatest
czygetIfExist
funkcja?-v
Nie działa na tablicach na moich CentOS 7.7.1908 z bash 4.2.46. Kod z pierwszego bloku kodu jest drukowanynot exist
we wszystkich przypadkach pod tym bashem. (Próbowano też[$i]
zamiast[i]
, bez różnicy)testowane w 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
źródło
+
rozwinięcia parametrów, aby zastąpić pustą wartość jakimś symbolem zastępczym, takim jak podkreślenie. Na przykładdeclare -A a[x]=;[[ ${a[x]} ]];echo $?
wydruki1
, aledeclare -A a[x]=;[[ ${a[x]+_} ]];echo $?
wydruki0
.A co z
-z
testem i:-
operatorem?Na przykład ten skrypt:
#!/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
Wydruki:
ABC is set DEF is set
źródło
To najłatwiejszy sposób, jaki znalazłem dla skryptów.
<search>
jest ciągiem, który chcesz znaleźć,ASSOC_ARRAY
nazwą zmiennej przechowującej twoją tablicę asocjacyjną.W zależności od tego, co chcesz osiągnąć:
klucz istnieje :
if grep -qe "<search>" <(echo "${!ASSOC_ARRAY[@]}"); then echo key is present; fi
klucz nie istnieje :
if ! grep -qe "<search>" <(echo "${!ASSOC_ARRAY[@]}"); then echo key not present; fi
wartość istnieje :
if grep -qe "<search>" <(echo "${ASSOC_ARRAY[@]}"); then echo value is present; fi
wartość nie istnieje :
if ! grep -qe "<search>" <(echo "${ASSOC_ARRAY[@]}"); then echo value not present; fi
źródło
Napisałem funkcję, aby sprawdzić, czy klucz istnieje w tablicy w 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 }
Przykład
declare -A my_array my_array['foo']="bar" if [[ "$(array_key_exists 'my_array' 'foo'; echo $?)" = "0" ]]; then echo "OK" else echo "ERROR" fi
Testowany z GNU bash, wersja 4.1.5 (1) -release (i486-pc-linux-gnu)
źródło