Respuestas:
En Bash 4, puede usar matrices asociativas:
# set up array of constants
declare -A array
for constant in foo bar baz
do
array[$constant]=1
done
# test for existence
test1="bar"
test2="xyzzy"
if [[ ${array[$test1]} ]]; then echo "Exists"; fi # Exists
if [[ ${array[$test2]} ]]; then echo "Exists"; fi # doesn't
Para configurar la matriz inicialmente, también puede hacer asignaciones directas:
array[foo]=1
array[bar]=1
# etc.
o de esta manera:
array=([foo]=1 [bar]=1 [baz]=1)
${array[$test1]}
es simple pero tiene un problema: no funcionará si lo usa set -u
en sus scripts (lo cual se recomienda), ya que obtendría "variable independiente".
set -u
: davidpashley.com/articles/writing-robust-shell-scripts.html , blog.hashbang0.com/2010/05/18/robust-bash-scripts-part-one , openews.net/2012/bash- script-to-write-robusto .
Es una vieja pregunta, pero creo que lo que es la solución más simple no ha aparecido todavía: test ${array[key]+_}
. Ejemplo:
declare -A xs=([a]=1 [b]="")
test ${xs[a]+_} && echo "a is set"
test ${xs[b]+_} && echo "b is set"
test ${xs[c]+_} && echo "c is set"
Salidas:
a is set
b is set
Para ver cómo funciona, verifique esto .
env
para evitar ambigüedades en alias, programas y otras funciones que pueden haber adoptado el nombre "prueba". Como arriba env test ${xs[a]+_} && echo "a is set"
. También puede obtener esta funcionalidad usando corchetes dobles, el mismo truco y luego verificando si es nulo:[[ ! -z "${xs[b]+_}" ]] && echo "b is set"
[[ ${xs[b]+set} ]]
Hay una manera de probar si existe un elemento de una matriz asociativa (no establecido), esto es diferente de vacío:
isNotSet() {
if [[ ! ${!1} && ${!1-_} ]]
then
return 1
fi
}
Entonces úsalo:
declare -A assoc
KEY="key"
isNotSet assoc[${KEY}]
if [ $? -ne 0 ]
then
echo "${KEY} is not set."
fi
if ! some_check then return 1
= some_check
. Por lo tanto: isNotSet() { [[ ... ]] }
. Verifique mi solución a continuación, puede hacerlo en una simple verificación.
Puede ver si una entrada está presente canalizando los contenidos de la matriz a grep.
printf "%s\n" "${mydata[@]}" | grep "^${val}$"
También puede obtener el índice de una entrada con grep -n, que devuelve el número de línea de una coincidencia (recuerde restar 1 para obtener un índice basado en cero) Esto será razonablemente rápido, excepto para matrices muy grandes.
# given the following data
mydata=(a b c "hello world")
for val in a c hello "hello world"
do
# get line # of 1st matching entry
ix=$( printf "%s\n" "${mydata[@]}" | grep -n -m 1 "^${val}$" | cut -d ":" -f1 )
if [[ -z $ix ]]
then
echo $val missing
else
# subtract 1. Bash arrays are zero-based, but grep -n returns 1 for 1st line, not 0
echo $val found at $(( ix-1 ))
fi
done
a found at 0
c found at 2
hello missing
hello world found at 3
explicación:
$( ... )
es lo mismo que usar backticks para capturar la salida de un comando en una variable printf
Produce mydata un elemento por línea @
lugar de *.
esto, evitan dividir "hello world" en 2 líneas)grep
busca una cadena exacta: ^
y $
coincide con el comienzo y el final de la líneagrep -n
devuelve la línea #, en forma de 4: hola mundo grep -m 1
encuentra solo el primer partidocut
extrae solo el número de línea Por supuesto, puede doblar la resta en el comando. Pero luego prueba para -1 por falta:
ix=$(( $( printf "%s\n" "${mydata[@]}" | grep -n -m 1 "^${val}$" | cut -d ":" -f1 ) - 1 ))
if [[ $ix == -1 ]]; then echo missing; else ... fi
$(( ... ))
hace aritmética de enterosNo creo que pueda hacerlo correctamente sin bucle a menos que tenga muy datos limitados en la matriz.
Aquí hay una variante simple, esto diría correctamente que "Super User"
existe en la matriz. Pero también diría que "uper Use"
está en la matriz.
MyArray=('Super User' 'Stack Overflow' 'Server Fault' 'Jeff' );
FINDME="Super User"
FOUND=`echo ${MyArray[*]} | grep "$FINDME"`
if [ "${FOUND}" != "" ]; then
echo Array contains: $FINDME
else
echo $FINDME not found
fi
#
# If you where to add anchors < and > to the data it could work
# This would find "Super User" but not "uper Use"
#
MyArray2=('<Super User>' '<Stack Overflow>' '<Server Fault>' '<Jeff>' );
FOUND=`echo ${MyArray2[*]} | grep "<$FINDME>"`
if [ "${FOUND}" != "" ]; then
echo Array contains: $FINDME
else
echo $FINDME not found
fi
El problema es que no hay una manera fácil de agregar los anclajes (que se me ocurra) además de recorrer la matriz. A menos que pueda agregarlos antes de ponerlos en la matriz ...
grep "\b$FINDME\b"
). Probablemente podría trabajar con constantes no alfanuméricos que no tienen espacios, con "(^| )$FINDME(\$| )"
(o algo así ... nunca he podido saber qué sabor de usos de expresiones regulares grep.)
#!/bin/bash
function in_array {
ARRAY=$2
for e in ${ARRAY[*]}
do
if [[ "$e" == "$1" ]]
then
return 0
fi
done
return 1
}
my_array=(Drupal Wordpress Joomla)
if in_array "Drupal" "${my_array[*]}"
then
echo "Found"
else
echo "Not found"
fi
in_array
. Saludos
${ARRAY[@]}
debería usarse.