¿Hay una buena manera de verificar si una matriz tiene un elemento en bash (mejor que recorrerlo)?
Alternativamente, ¿hay otra forma de verificar si un número o una cadena es igual a cualquiera de un conjunto de constantes predefinidas?
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 usaset -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:Salidas:
Para ver cómo funciona, verifique esto .
fuente
env
para evitar ambigüedades en alias, programas y otras funciones que pueden haber adoptado el nombre "prueba". Como arribaenv 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:
Entonces úsalo:
fuente
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.
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.
explicación:
$( ... )
es lo mismo que usar backticks para capturar la salida de un comando en una variableprintf
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 mundogrep -m 1
encuentra solo el primer partidocut
extrae solo el número de líneaPor supuesto, puede doblar la resta en el comando. Pero luego prueba para -1 por falta:
$(( ... ))
hace aritmética de enterosfuente
No 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.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 ...
fuente
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.)fuente
in_array
. Saludos${ARRAY[@]}
debería usarse.