817 Stimmen

Prüfen, ob ein Bash-Array einen Wert enthält

Wie kann man in Bash am einfachsten testen, ob ein Array einen bestimmten Wert enthält?

46voto

Sean DiSanti Punkte 437

Normalerweise verwende ich nur:

inarray=$(echo ${haystack[@]} | grep -o "needle" | wc -w)

Ein Wert ungleich Null bedeutet, dass eine Übereinstimmung gefunden wurde.

... um das Problem zu lösen, dass es mit needle1 und needle2 nicht funktioniert, wenn Sie nur eine exakte Übereinstimmung wollen, nicht mehr und nicht weniger, fügen Sie einfach ein w Kennzeichen nach dem -o für eine Übereinstimmung mit einem ganzen Wort:

inarray=$(echo ${haystack[@]} | grep -ow "needle" | wc -w)

24voto

LeoRochael Punkte 12443

Wenn Sie Leistung benötigen, möchten Sie nicht bei jeder Suche eine Schleife über Ihr gesamtes Array laufen lassen.

In diesem Fall können Sie ein assoziatives Array (Hashtabelle oder Wörterbuch) erstellen, das einen Index dieses Arrays darstellt. Das heißt, jedes Array-Element wird auf seinen Index im Array abgebildet:

make_index () {
  local index_name=$1
  shift
  local -a value_array=("$@")
  local i
  # -A means associative array, -g means create a global variable:
  declare -g -A ${index_name}
  for i in "${!value_array[@]}"; do
    eval ${index_name}["${value_array[$i]}"]=$i
  done
}

Dann können Sie es so verwenden:

myarray=('a a' 'b b' 'c c')
make_index myarray_index "${myarray[@]}"

Und testen Sie die Mitgliedschaft wie folgt:

member="b b"
# the "|| echo NOT FOUND" below is needed if you're using "set -e"
test "${myarray_index[$member]}" && echo FOUND || echo NOT FOUND

Oder auch:

if [ "${myarray_index[$member]}" ]; then 
  echo FOUND
fi

Beachten Sie, dass diese Lösung auch dann das Richtige tut, wenn der getestete Wert oder die Array-Werte Leerzeichen enthalten.

Als Bonus erhalten Sie mit auch den Index des Wertes innerhalb des Arrays:

echo "<< ${myarray_index[$member]} >> is the index of $member"

22voto

estani Punkte 20703

Ein weiterer One-Liner ohne Funktion:

(for e in "${array[@]}"; do [[ "$e" == "searched_item" ]] && exit 0; done) && echo "found" || echo "not found"

Danke @Qwerty für den Hinweis auf die Leerzeichen!

entsprechende Funktion:

find_in_array() {
  local word=$1
  shift
  for e in "$@"; do [[ "$e" == "$word" ]] && return 0; done
  return 1
}

Beispiel:

some_words=( these are some words )
find_in_array word "${some_words[@]}" || echo "expected missing! since words != word"

14voto

Rosta Kosta Punkte 135

Wie prüft man, ob ein Bash-Array einen Wert enthält?


Falsch positive Übereinstimmung

array=(a1 b1 c1 d1 ee)

[[ ${array[*]} =~ 'a' ]] && echo 'yes' || echo 'no'
# output:
yes

[[ ${array[*]} =~ 'a1' ]] && echo 'yes' || echo 'no'
# output:
yes

[[ ${array[*]} =~ 'e' ]] && echo 'yes' || echo 'no'
# output:
yes

[[ ${array[*]} =~ 'ee' ]] && echo 'yes' || echo 'no'
# output:
yes

Genaue Übereinstimmung

Um nach einer exakten Übereinstimmung zu suchen, muss Ihr Regex-Muster zusätzliche Leerzeichen vor und nach dem Wert hinzufügen, wie (^|[[:space:]])"VALUE"($|[[:space:]])

# Exact match

array=(aa1 bc1 ac1 ed1 aee)

if [[ ${array[*]} =~ (^|[[:space:]])"a"($|[[:space:]]) ]]; then
    echo "Yes";
else
    echo "No";
fi
# output:
No

if [[ ${array[*]} =~ (^|[[:space:]])"ac1"($|[[:space:]]) ]]; then
    echo "Yes";
else
    echo "No";
fi
# output:
Yes

find="ac1"
if [[ ${array[*]} =~ (^|[[:space:]])"$find"($|[[:space:]]) ]]; then
    echo "Yes";
else
    echo "No";
fi
# output:
Yes

Weitere Beispiele für die Verwendung finden Sie unter aquí

13voto

Dennis Williamson Punkte 322329

Wenn Sie einen schnellen und schmutzigen Test durchführen wollen, um zu sehen, ob es sich lohnt, über das gesamte Array zu iterieren, um eine genaue Übereinstimmung zu erhalten, kann Bash Arrays wie Skalare behandeln. Testen Sie auf eine Übereinstimmung im Skalar, wenn es keine gibt, können Sie die Schleife überspringen und Zeit sparen. Offensichtlich kann es zu falsch positiven Ergebnissen kommen.

array=(word "two words" words)
if [[ ${array[@]} =~ words ]]
then
    echo "Checking"
    for element in "${array[@]}"
    do
        if [[ $element == "words" ]]
        then
            echo "Match"
        fi
    done
fi

Dies führt zur Ausgabe von "Checking" und "Match". Mit array=(word "two words" something) wird nur "Prüfen" ausgegeben. Mit array=(word "two widgets" something) gibt es keine Ausgabe.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X