En Bourne, como el shell que admite la variable de matriz, podemos usar algún análisis para verificar si la variable es una matriz.
Todos los comandos a continuación se ejecutaron después de ejecutarse a=(1 2 3)
.
zsh
:
$ declare -p a
typeset -a a
a=( 1 2 3 )
bash
:
$ declare -p a
declare -a a='([0]="1" [1]="2" [2]="3")'
ksh93
:
$ typeset -p a
typeset -a a=(1 2 3)
pdksh
y su derivada:
$ typeset -p a
set -A a
typeset a[0]=1
typeset a[1]=2
typeset a[2]=3
yash
:
$ typeset -p a
a=('1' '2' '3')
typeset a
Un ejemplo en bash
:
if declare -p var 2>/dev/null | grep -q 'declare -a'; then
echo array variable
fi
Este enfoque es demasiado trabajo y necesita generar una subshell. Usar otro shell incorporado como =~
en [[ ... ]]
no necesita un subshell, pero sigue siendo demasiado complicado.
¿Hay alguna manera más fácil de realizar esta tarea?
Respuestas:
No creo que puedas, y no creo que realmente haga ninguna diferencia.
Eso hace lo mismo en cualquiera de
ksh93
ybash
. Parece que posiblemente todas las variables son matrices en esos shells, o al menos cualquier variable regular a la que no se le hayan asignado atributos especiales, pero no verifiqué mucho de eso.El
bash
manual habla sobre diferentes comportamientos para una matriz frente a una variable de cadena cuando se usan+=
asignaciones, pero luego cubre y establece que la matriz solo se comporta de manera diferente en un contexto de asignación compuesto .También establece que una variable se considera una matriz si a cualquier subíndice se le ha asignado un valor, e incluye explícitamente la posibilidad de una cadena nula. Arriba puede ver que una asignación regular definitivamente resulta en la asignación de un subíndice, por lo que supongo que todo es una matriz.
Prácticamente, posiblemente puede usar:
... para identificar claramente las variables establecidas a las que solo se les ha asignado un subíndice único de valor 0.
fuente
${a[1]-not array}
puede hacer la tarea, ¿no?bash
manual: una variable de matriz se considera establecida si a un subíndice se le ha asignado un valor. La cadena nula es un valor válido. Si se asigna un subíndice, es una matriz por especificación. En la práctica, tampoco, porque puedes hacerloa[5]=x
. Supongo que[ 1 -eq "${#a[@]}" ] && [ -n "${a[0]+1}" ]
podría funcionar.Entonces, ¿quieres efectivamente solo la parte media
declare -p
sin la basura a su alrededor?Podrías escribir una macro como:
para que puedas hacer:
(Una simple función no funcionará si desea utilizar esto en variables locales de función).
Con alias
fuente
alias vartype="$VARTYPE"
... o simplemente no definía$VARTYPE
nada, debería funcionar, ¿verdad? solo debería necesitar esashopt
cosabash
porque rompe con la especificación con respecto a laalias
expansión en los scripts.En zsh
fuente
echo ${(t)var}
es más simple. Gracias por esto.Para probar la variable var, con
Es posible probar si hay más de un índice de matriz:
Si el primer valor del índice no es cero:
La única confusión difícil es cuando solo hay un valor de índice y ese valor es cero (o uno).
Para esa condición, es posible usar un efecto secundario al tratar de eliminar un elemento de matriz de una variable que no es una matriz:
Esto funciona correctamente para bash:
Para zsh, el índice puede ser 1 (a menos que haya un modo compatible activo).
El subconjunto es necesario para evitar el efecto secundario de borrar el índice 0 de la var.
No he encontrado la manera de hacerlo funcionar en ksh.
Editar 1
Esta función solo funciona en bash4.2 +
Editar 2
Esto también funciona solo para bash4.2 +
Nota: Esto dará falsos positivos si var contiene las cadenas probadas.
fuente
( unset "var[0]" 2>/dev/null; ) && echo "var is an array."
informa correctamente que var es una matriz cuando var se ha establecido envar=()
una matriz con cero elementos. Actúa exactamente igual a declarar.grep -E
lugar degrep -P
evitar la dependencia de GNU grep.-a
, como esto:declare -airl var='()'
. Por lo tanto, la prueba grep funcionará .Para bash , es un truco (aunque documentado): intente usar
typeset
para eliminar el atributo "array":(No puede hacer esto
zsh
, le permite convertir una matriz a un escalar, yabash
que está explícitamente prohibido).Entonces:
O en una función, observando las advertencias al final:
Tenga en cuenta el uso de
typeset -g
(bash-4.2 o posterior), esto es necesario dentro de una función para quetypeset
(syn.declare
) No funcione comolocal
y bloquee el valor que está tratando de inspeccionar. Esto tampoco maneja los tipos de función "variable", puede agregar otra prueba de ramificación utilizandotypeset -f
si es necesario.Otra opción (casi completa) es usar esto:
Sin embargo, hay un pequeño problema: una matriz con un solo subíndice de 0 coincide con dos de las condiciones anteriores. Esto es algo a lo que mikeserv también hace referencia, bash realmente no tiene una distinción difícil, y algo de esto (si marca el registro de cambios) puede atribuirse a ksh y a la compatibilidad con cómo
${name[*]}
o${name[@]}
comportarse en una no matriz.Entonces, una solución parcial es:
He usado en el pasado una variación de esto:
Sin embargo, esto también necesita un subshell.
Una técnica posiblemente más útil es
compgen
:Esto enumerará todas las matrices indexadas, sin embargo, las matrices asociativas no se manejan especialmente (hasta bash-4.4) y aparecen como variables regulares (
compgen -A variable
)fuente
typeset +a
también informa un error en ksh. Sin embargo, no en zsh.Respuesta corta:
Para las dos capas que introdujeron esta notación (
bash
yksh93
) una variable escalar es solo una matriz con un solo elemento .Tampoco necesita una declaración especial para crear una matriz. Solo la asignación es suficiente, y una asignación simple
var=value
es idéntica avar[0]=value
.fuente
bash -c 'unset var; var=foo; typeset -p var'
. ¿Bash answer informa una matriz (necesita un -a) ?. Ahora compare con:bash -c 'unset var; var[12]=foo; typeset -p var'
. ¿Por qué hay una diferencia?. R: El shell mantiene (para bien o para mal) una noción de qué vars son escalares o matrices. El shell ksh mezcla ambos conceptos en uno.Yash
array
orden interna tiene algunas opciones que sólo funcionan con variables de matriz. Ejemplo: la-d
opción informará un error en la variable sin matriz:Entonces podemos hacer algo como esto:
Este enfoque no funcionará si la variable de matriz es de solo lectura . Intentando modificar una variable de solo lectura que conduce a un error:
fuente
fuente