Wie teste ich, ob sich ein Element in einem Bash-Array befindet?

15

Hilfe für ein einfaches Skript

#!/bin/bash

array1=(
prova1
prova2
slack64
)

a="slack64"
b="ab"

if [ $a = $b ]
then
      echo "$a = $b : a is equal to b"
else
      echo "$a = $b: a is not equal to b"
fi

Dieses Skript funktioniert einfach nicht. Ich möchte ein Skript, das prüft, ob slack64 in einer Liste vorhanden ist (ich verwende ein Array), und mir einfach sagt, ob yes vorhanden ist oder nein. Ich weiß nicht, wie man ein Array mit einer einzelnen Variablen vergleicht.

Elbarna
quelle
4
Wo funktioniert die array1arbeit
Tachomi

Antworten:

17

Verwenden Sie eine andere Art von Array: Verwenden Sie anstelle eines ganzzahligen Arrays ein assoziatives Array, damit der Schlüssel (Index) das ist, nach dem Sie suchen. bash-4.0oder später wird dafür benötigt.

declare -A array1=( 
 [prova1]=1  [prova2]=1  [slack64]=1
)

a=slack64
[[ -n "${array1[$a]}" ]] && printf '%s is in array\n' "$a"

Im obigen Beispiel kümmern wir uns nicht wirklich um die Werte, sie müssen dafür nur nicht leer sein. Sie können ein indiziertes Array in ein neues assoziatives Array "invertieren", indem Sie den Schlüssel und den Wert austauschen:

declare -a array1=( 
 prova1 prova2 slack64
)
declare -A map    # required: declare explicit associative array
for key in "${!array1[@]}"; do map[${array1[$key]}]="$key"; done  # see below

a=slack64
[[ -n "${map[$a]}" ]] && printf '%s is in array\n' "$a"

Dies kann sich auszahlen, wenn Sie große Arrays haben, die häufig durchsucht werden, da die Implementierung von assoziativen Arrays eine bessere Leistung erzielt als Array-Traversing-Schleifen. Es ist jedoch nicht für jeden Anwendungsfall geeignet, da es keine Duplikate verarbeiten kann (obwohl Sie den Wert anstelle von nur 1 wie oben als Zähler verwenden können) und keinen leeren Index verarbeiten kann.

Brechen Sie die komplexe Linie oben aus, um die "Inversion" zu erklären:

for key in "${!a[@]}"     # expand the array indexes to a list of words
do 
  map[${a[$key]}]="$key"  # exchange the value ${a[$key]} with the index $key
done
mr.spuratic
quelle
14

Der einfache Weg ist, mit einer Schleife zu iterieren:

var=ab
for item in "${array[@]}"; do
    [[ $var == "$item" ]] && echo "$var present in the array"
done
Gilles Quenot
quelle
? [[ a == aaa ]]ist falsch aber eine Übereinstimmung aaa nein?
Gilles Quenot
SO sollte der OP informiert werden, dass er darauf achten muss, ob die Werte Sonderzeichen enthalten können, wie [ ]: Zeichenklasse (Globs)
Gilles Quenot
Ich sehe keinen Unterschied zwischen = und == in Bash [[ ]]für das, was Sie gesagt haben. Hast du getestet?
Gilles Quenot
2

Mit zsh:

array1=(
  prova1
  prova2
  slack64
)

a=slack64

if ((array1[(Ie)$a])); then
  printf '%s\n' "$a in array1"
fi
Stéphane Chazelas
quelle
2

Diese Funktion arbeitet mit assoziativen Arrays.

Mit dieser Funktion können wir eine der folgenden Aktionen ausführen:

- überprüfe ob das Array einen bestimmten Schlüssel hat -----------------> inArray "myKey" $ {! myArray [@]} "

- überprüfe, ob das Array einen bestimmten Wert enthält ---------> inArray "myValue" "$ {myArray [@]}"

function inArray # ( keyOrValue, arrayKeysOrValues ) 
{
  local e
  for e in "${@:2}"; do 
    [[ "$e" == "$1" ]] && return 0; 
  done
  return 1
}

declare -A arr
arr[doo]=55

inArray "doo" "${!arr[@]}"
echo $?     # 0 
inArray "bla" "${!arr[@]}"
echo $?     # 1 
inArray "55" "${arr[@]}"
echo $?     # 0
Leng
quelle
2

Sie können dafür auch grep verwenden:

array1 = (prova1 prova2 slack64)
a = slack64
if (printf '% s \ n' "$ {array1 [@]}" | grep -xq $ a); dann
    Echo "es ist in"
fi
Petr Ketner
quelle
1
Dies setzt voraus, dass die Array-Elemente keine Zeilenumbrüche enthalten (und Leerzeichen und Platzhalter, da Sie das Anführungszeichen vergessen haben $a, und beginnen Sie nicht damit, dass -Sie das vergessen haben --). Sie könnten %s\0anstelle von %s\nund verwenden grep --null(vorausgesetzt, GNU grep oder compatible), da bash-Variablen das NUL-Zeichen ohnehin nicht enthalten können. Sie müssten auch speziell den Fall eines leeren Arrays behandeln (da dieser Befehl printf dasselbe ausgibt wie für ein Array mit einem leeren Element). Beachten Sie auch, dass Sie hier keine Subshell starten müssen.
Stéphane Chazelas
Ja, es gilt für die einfachen Arrays wie das in der Frage.
Petr Ketner