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?

889voto

Keegan Punkte 9528

Dieser Ansatz hat den Vorteil, dass keine Schleife über alle Elemente gezogen werden muss (zumindest nicht explizit). Aber da array_to_string_internal() en array.c Schleift immer noch über Array-Elemente und verkettet sie zu einer Zeichenkette. Es ist wahrscheinlich nicht effizienter als die vorgeschlagenen Schleifenlösungen, aber es ist besser lesbar.

if [[ " ${array[*]} " =~ " ${value} " ]]; then
    # whatever you want to do when array contains value
fi

if [[ ! " ${array[*]} " =~ " ${value} " ]]; then
    # whatever you want to do when array doesn't contain value
fi

Beachten Sie, dass es in Fällen, in denen der gesuchte Wert eines der Wörter in einem Array-Element mit Leerzeichen ist, zu falsch positiven Ergebnissen führen kann. Zum Beispiel

array=("Jack Brown")
value="Jack"

Der Regex sieht "Jack" als im Array enthalten an, obwohl er es nicht ist. Sie müssen also Folgendes ändern IFS und die Trennzeichen in Ihrer Regex, wenn Sie diese Lösung trotzdem verwenden wollen, etwa so

IFS="|"
array=("Jack Brown${IFS}Jack Smith")
value="Jack"

if [[ "${IFS}${array[*]}${IFS}" =~ "${IFS}${value}${IFS}" ]]; then
    echo "true"
else
    echo "false"
fi

unset IFS # or set back to original IFS if previously set

Dies führt zur Ausgabe von "false".

Natürlich kann dies auch als Testanweisung verwendet werden, so dass sie in einem Einzeiler ausgedrückt werden kann

[[ " ${array[*]} " =~ " ${value} " ]] && echo "true" || echo "false"

482voto

patrik Punkte 4605

Nachstehend finden Sie eine kleine Funktion, mit der Sie dies erreichen können. Der Suchstring ist das erste Argument und der Rest sind die Array-Elemente:

set +e #otherwise the script will exit on error
containsElement () {
  local e match="$1"
  shift
  for e; do [[ "$e" == "$match" ]] && return 0; done
  return 1
}

Ein Testlauf dieser Funktion könnte folgendermaßen aussehen:

$ array=("something to search for" "a string" "test2000")
$ containsElement "a string" "${array[@]}"
$ echo $?
0
$ containsElement "blaha" "${array[@]}"
$ echo $?
1

157voto

JellicleCat Punkte 26058

Einzeilige Lösung

printf '%s\0' "${myarray[@]}" | grep -F -x -z -- 'myvalue'

Erläuterung

Le site printf Anweisung gibt jedes Element des Arrays aus, begrenzt durch Nullzeichen.

Le site grep Anweisung verwendet die folgenden Flags, um ein Element zu finden, das Folgendes enthält まさに die Zeichenkette, die als myvalue (nicht mehr und nicht weniger):

  • -z / --null-data - Die Zeilen werden mit einem Null-Byte anstelle eines Zeilenumbruchs abgeschlossen.
  • -F / --fixed-strings - Interpretieren Sie PATTERNS als feste Zeichenketten, nicht als reguläre Ausdrücke.
  • -x / --line-regexp - Wählen Sie nur die Treffer aus, die genau mit der gesamten Zeile übereinstimmen.
  • -- - markiert das Ende der Befehlszeilenoptionen, so dass Grep den Prozess " myvalue " als Nicht-Options-Argument, auch wenn es mit einem Bindestrich beginnt

Warum verwenden wir ein Null-Byte \0 anstelle eines Zeilenumbruchs \n ? Ihr Array kann tatsächlich Zeilenumbrüche innerhalb seiner Elemente enthalten. (Wenn Sie wissen, dass das nicht der Fall ist, können Sie das -z grep-Option und Substitut %s\n als Ihr erstes printf-Argument).


Verwendung

Um dies zu verdeutlichen if ... then Erklärung:

if printf '%s\0' "${myarray[@]}" | grep -Fxqz -- 'myvalue'; then
    # ...
fi

Ich habe eine -q Flagge zum grep Ausdruck, so dass er keine Übereinstimmungen ausgibt, sondern nur die Existenz einer Übereinstimmung als "wahr" behandelt.

Update : Danke, presto8, für den Hinweis auf die --line-regexp Flagge. Danke, Tino, für den Hinweis auf den Fall, dass Zeilenumbrüche innerhalb von Array-Elementen vorkommen können.

77voto

Scott Punkte 2033
for i in "${array[@]}"
do
    if [ "$i" -eq "$yourValue" ] ; then
        echo "Found"
    fi
done

Für Streicher:

for i in "${array[@]}"
do
    if [ "$i" == "$yourValue" ] ; then
        echo "Found"
    fi
done

56voto

ghostdog74 Punkte 305138
$ myarray=(one two three)
$ case "${myarray[@]}" in  *"two"*) echo "found" ;; esac
found

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