Come posso verificare se un articolo si trova in un array bash?


15

Aiuto per uno script semplice

#!/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

Questo script semplicemente non funziona, voglio uno script che controlli se slack64 è presente in un elenco (io uso un array) e semplicemente mi dia, sì è presente o no. Non so come confrontare un array con una singola variabile.


4
Dove array1funziona?
Tachomi,

Risposte:


17

Usa un diverso tipo di array: piuttosto che un array con indice intero, usa un array associativo, quindi la chiave (indice) è ciò che verifichi. bash-4.0o successivo è richiesto per questo.

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

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

Quanto sopra non ci interessa davvero dei valori, devono solo essere non vuoti per questo. È possibile "invertire" un array indicizzato in un nuovo array associativo scambiando la chiave e il valore:

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"

Questo può ripagare se si hanno array di grandi dimensioni che vengono frequentemente cercati, poiché l'implementazione di array associativi avrà prestazioni migliori rispetto ai loop che attraversano gli array. Tuttavia, non si adatta a tutti i casi d'uso, poiché non può gestire i duplicati (sebbene sia possibile utilizzare il valore come contatore, anziché solo 1 come sopra) e non può gestire un indice vuoto.

Rompere la complessa linea sopra, per spiegare l '"inversione":

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

14

Il modo più semplice è iterare con un ciclo:

var=ab
for item in "${array[@]}"; do
    [[ $var == "$item" ]] && echo "$var present in the array"
done

? [[ a == aaa ]]è falso ma una partita aaa no?
Gilles Quenot

Quindi l'OP dovrebbe essere informato che deve fare attenzione se i valori possono contenere caratteri speciali, come [ ]: classe di caratteri (globs)
Gilles Quenot

Non vedo alcuna differenza tra = e == in bash [[ ]]per quello che hai detto. Hai provato?
Gilles Quenot,

2

Con zsh:

array1=(
  prova1
  prova2
  slack64
)

a=slack64

if ((array1[(Ie)$a])); then
  printf '%s\n' "$a in array1"
fi

2

Questa funzione funziona con array associativi.

Possiamo usare questa funzione per eseguire una delle seguenti operazioni:

- controlla se l'array ha una determinata chiave -----------------> inArray "myKey" $ {! myArray [@]} "

- controlla se l'array contiene un certo valore ---------> 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

2

Puoi anche usare grep per questo:

array1 = (prova1 prova2 slack64)
a = slack64
if (printf '% s \ n' "$ {array1 [@]}" | grep -xq $ a); poi
    echo "è dentro"
fi

1
Ciò presuppone che gli elementi dell'array non contengano caratteri di nuova riga (e spazi vuoti e caratteri jolly come hai dimenticato di citare $a, e non iniziare -come hai dimenticato --). È possibile utilizzare %s\0anziché %s\ne utilizzare grep --null(presupponendo GNU grep o compatibile) poiché le variabili bash non possono comunque contenere il carattere NUL. Dovresti anche gestire il caso di un array vuoto specialmente (poiché quel comando printf stamperebbe la stessa cosa di un array con un elemento vuoto). Si noti inoltre che non è necessario avviare una subshell qui.
Stéphane Chazelas,

sì, è applicabile su array semplici come quello in questione.
Petr Ketner,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.