2012-11-04 9 views
53

Verwendung:Der einfachste Weg, um nach einem Index oder einem Schlüssel in einem Array zu suchen?

set -o nounset 

1) wie ein indiziertes Array mit:

myArray=("red" "black" "blue") 

Welche der kürzeste Weg 1, wenn Element zu überprüfen ist, festgelegt ist?
Manchmal benutze ich die folgenden:

test "${#myArray[@]}" -gt "1" && echo "1 exists" || echo "1 doesn't exist" 

Ich möchte wissen, ob es eine bevorzugte ist.

2) Wie man mit nicht aufeinanderfolgenden Indexen umgeht?

myArray=() 
myArray[12]="red" 
myArray[51]="black" 
myArray[129]="blue" 

Wie schnell überprüfen, dass "51" zum Beispiel bereits eingestellt ist?

3) Wie geht man mit assoziativen Arrays um?

declare -A myArray 
myArray["key1"]="red" 
myArray["key2"]="black" 
myArray["key3"]="blue" 

Wie schnell überprüfen, dass "key2" zum Beispiel bereits verwendet wird?

Dank


Der einfachste Weg scheint mir EDITED:

if test "${myArray['key_or_index']+isset}" 
    then 
     echo "yes" 
    else 
     echo "no" 
fi; 

Dies funktioniert sowohl für indizierte und assoziative Arrays. Keine Fehler mit Set -o Nomenset angezeigt.
Dank DoubleDown für den Headup.

Antwort

79

Zur prüfen, ob das Element gesetzt ist (gilt sowohl für indizierte und assoziative Array)

[ ${array[key]+abc} ] && echo "exists" 

Im Allgemeinen, was ${array[key]+abc} tut

ist
  • wenn array[key] gesetzt ist, zurückkehren abc
  • wenn array[key] nicht gesetzt ist, kehren nichts


Referenzen:

  1. Siehe Parameter Expansion in Bash Handbuch und die kleine Hinweis

    wenn der Doppelpunkt weggelassen wird, werden nur die Betreiber Tests für Existenz [von Parameter]

  2. Diese Antwort ist eigentlich aus den Antworten auf diese Frage SO angepasst: How to tell if a string is not defined in a bash shell script?


Umhüller Funktion:

exists(){ 
    if [ "$2" != in ]; then 
    echo "Incorrect usage." 
    echo "Correct usage: exists {key} in {array}" 
    return 
    fi 
    eval '[ ${'$3'[$1]+muahaha} ]' 
} 

Zum Beispiel

if ! exists key in array; then echo "No such array element"; fi 
+0

Ich löste auf diese Weise: wenn Test "$ {myArray ['key_or_index'] + isset}"; dann echo "ja"; sonst echo "nein"; fi; Es scheint mir der einfachste Weg zu sein und gilt für indizierte und assoziative Arrays. Danke –

+2

+1! Danke für die '$ {var + val}' -Notation! Ich las wieder "Man Bash" und ich stellte fest, dass ich es vorher übersprungen hatte! – TrueY

+1

@doubleDown Wie benutzt man [$ {array [key] + abc}] in einer if-Klausel, um nur etwas zu tun, wenn [$ {array [key] + abc}] nicht existiert? – olala

7

Leider Bash geben keinen Weg, um zwischen und undefined Variable zu unterscheiden.

Aber es gibt einige Möglichkeiten:

$ 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 

(geben keine Antwort)

Und für assoziatives Array, können Sie die Verwendung gleich:

$ 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 

Sie die Arbeit erledigen können, ohne die Notwendigkeit von externen Tools (keine printf | grep als pure Bash), und warum nicht, Build checkIfExist() als neue bash Funktion:

$ 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 

oder Erstellen eine neue getIfExist bash Funktion, die den gewünschten Wert und Ausgang mit falschem Ergebniscode zurück, wenn Sollwert nicht vorhanden ist:

$ 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 
+0

es war sehr interessant, weiter durch aaaall dies. Danke –

4

in bash getestet 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 
+0

Das schlägt fehl, wenn der Wert des Schlüssels eine leere Zeichenfolge ist. Als Workaround können Sie die '+' Parametererweiterung verwenden, um einen leeren Wert durch einen Platzhalter wie einen Unterstrich zu ersetzen. Zum Beispiel 'declare -A a [x] =; [[$ {a [x]}]]; echo $?' Druckt '1', aber' declare -A a [x] =; [[$ {a [ x] + _}]]; echo $? 'druckt' 0'. – user4669748

0

T Das ist der einfachste Weg, den ich für Skripte gefunden habe.

<search> ist die Zeichenfolge, die Sie finden wollen, ASSOC_ARRAY der Name der Variablen Ihre assoziatives Array zu halten.

Dependign auf das, was Sie erreichen wollen:

Schlüssel vorhanden:

if grep -qe "<search>" <(echo "${!ASSOC_ARRAY[@]}"); then echo key is present; fi 

Schlüssel nicht existiert:

if ! grep -qe "<search>" <(echo "${!ASSOC_ARRAY[@]}"); then echo key not present; fi 

Wert existiert:

if grep -qe "<search>" <(echo "${ASSOC_ARRAY[@]}"); then echo value is present; fi 

Wert existiert nicht:

if ! grep -qe "<search>" <(echo "${ASSOC_ARRAY[@]}"); then echo value not present; fi 
1

ich eine Funktion überprüfen geschrieben, wenn ein Schlüssel in einem Array in Bash vorhanden:

# 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 
} 

Beispiel

declare -A my_array 
my_array['foo']="bar" 

if [[ "$(array_key_exists 'my_array' 'foo'; echo $?)" = "0" ]]; then 
    echo "OK" 
else 
    echo "ERROR" 
fi 

Getestet mit GNU bash, Version 4.1.5 (1) -release (i486-pc-linux-gnu)

3

Von man bash, bedingte Ausdrücke:

-v varname 
       True if the shell variable varname is set (has been assigned a value). 

Beispiel:

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 

Dies zeigt, dass sowohl foo [bar] als auch foo [baz] gesetzt sind (auch wenn letztere auf einen leeren Wert gesetzt ist) und foo [quux] nicht.

Verwandte Themen