¿Cómo pruebo si un elemento está en una matriz bash?


15

Ayuda para un script simple

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

Este script simplemente no funciona, quiero un script que compruebe si slack64 está presente en una lista (uso una matriz), y simplemente dame, sí está presente o no. No sé cómo comparar una matriz con una sola variable.


44
¿De donde viene el array1trabajo?
tachomi

Respuestas:


17

Use un tipo diferente de matriz: en lugar de una matriz indexada con enteros, use una matriz asociativa, por lo que la clave (índice) es lo que estará buscando. bash-4.0o más tarde se requiere para esto.

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

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

En lo anterior, realmente no nos importan los valores, solo necesitan estar no vacíos para esto. Puede "invertir" una matriz indexada en una nueva matriz asociativa intercambiando la clave y el valor:

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"

Esto puede ser rentable si tiene matrices grandes que se buscan con frecuencia, ya que la implementación de matrices asociativas funcionará mejor que los bucles de recorrido de matrices. Sin embargo, no se adaptará a todos los casos de uso, ya que no puede manejar duplicados (aunque puede usar el valor como un contador, en lugar de solo 1 como arriba), y no puede manejar un índice vacío.

Desglosando la línea compleja de arriba, para explicar la "inversión":

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

La forma más directa es iterar con un bucle:

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

? [[ a == aaa ]]es falso pero una coincidencia aaa no?
Gilles Quenot

Entonces, el OP debe ser informado de que debe tener cuidado si los valores pueden contener caracteres especiales, como [ ]: clase de caracteres (globs)
Gilles Quenot

No veo diferencia entre = y == en bash [[ ]]por lo que dijiste. ¿Has probado?
Gilles Quenot

2

Con zsh:

array1=(
  prova1
  prova2
  slack64
)

a=slack64

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

2

Esta función funciona con matrices asociativas.

Podemos usar esta función para realizar una de las siguientes acciones:

- compruebe si la matriz tiene una clave determinada -----------------> inArray "myKey" $ {! myArray [@]} "

- verifique si la matriz contiene un cierto valor ---------> 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

También puedes usar grep para eso:

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

1
Eso supone que los elementos de la matriz no contienen caracteres de nueva línea (y espacios en blanco y comodines como se olvidó de citar $a, y no comience -como se olvidó --). Puede usar en %s\0lugar de %s\nusar grep --null(suponiendo GNU grep o compatible) ya que las variables bash no pueden contener el carácter NUL de todos modos. También necesitaría manejar el caso de una matriz vacía especialmente (ya que ese comando printf imprimiría lo mismo que para una matriz con un elemento vacío). También tenga en cuenta que no necesita iniciar una subshell aquí.
Stéphane Chazelas

sí, es aplicable en matrices simples como la de la pregunta.
Petr Ketner
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.