Suponiendo que usted quiere restringir a Bourne como conchas (muchas otras cáscaras como csh, tcsh, rc, eso fishmatrices de apoyo, pero escribir un guión compatible al mismo tiempo a Bourne como conchas y los que es complicado y generalmente tiene sentido, ya que son intérpretes para completamente diferente y idiomas incompatibles), tenga en cuenta que existen diferencias significativas entre las implementaciones.
Los shells tipo Bourne que admiten matrices son:
ksh88(esa es la primera implementación de matrices, ksh88 todavía se encuentra como kshen la mayoría de las unidades comerciales tradicionales donde también es la base sh)
- las matrices son unidimensionales
- Las matrices se definen como
set -A array foo baro set -A array -- "$var" ...si no puede garantizar que $varno comenzará con una -o +.
- Los índices de matriz comienzan en
0.
- Los elementos individuales de la matriz se asignan como
a[1]=value.
- Las matrices son escasas. Eso
a[5]=foofuncionará incluso si a[0,1,2,3,4]no están configurados y los dejará sin configurar.
${a[5]}para acceder al elemento del índice 5 (no necesariamente el sexto elemento si la matriz es escasa). El 5puede haber cualquier expresión aritmética.
- El tamaño de la matriz y el subíndice están limitados (a 4096).
${#a[@]} es el número de elemento asignado en la matriz (no el mayor índice asignado).
- no hay forma de conocer la lista de subíndices asignados (aparte de probar los elementos 4096 individualmente con
[[ -n "${a[i]+set}" ]]).
$aes el mismo que ${a[0]}. Es decir, las matrices de alguna manera extienden las variables escalares dándoles valores adicionales.
pdkshy derivados (esa es la base para, kshy algunas veces, shde varios BSD y fue la única implementación de código abierto de ksh antes de que se liberara la fuente de ksh93):
Principalmente como ksh88pero tenga en cuenta:
- Algunas implementaciones antiguas no eran compatibles
set -A array -- foo bar( --no era necesario allí).
${#a[@]}es uno más el índice del mayor índice asignado. ( a[1000]=1; echo "${#a[@]}"salidas 1001 a pesar de que la matriz tiene solo un elemento.
- en versiones más nuevas, el tamaño de la matriz ya no está limitado (excepto por el tamaño de los enteros).
- Las versiones recientes de
mkshtienen unos pocos operadores adicionales inspirados bash, ksh93o zshcomo asignaciones a la a=(x y), a+=(z), ${!a[@]}para obtener la lista de índices asignados.
zsh. zshmatrices están generalmente mejor diseñados y toman lo mejor de kshy cshmatrices. Son similares kshpero con diferencias significativas:
- los índices comienzan en 1, no en 0 (excepto en la
kshemulación), eso es consistente con la matriz Bourne (los parámetros de posición $ @, que zshtambién se exponen como su matriz $ argv) y las cshmatrices.
- son un tipo separado de las variables normales / escalares. Los operadores se aplican de manera diferente a ellos y como generalmente esperarías.
$ano es lo mismo ${a[0]}pero se expande a los elementos no vacíos de la matriz ( "${a[@]}"para todos los elementos como en ksh).
- son matrices normales, no matrices dispersas.
a[5]=1funciona pero asigna todos los elementos del 1 al 4 a la cadena vacía si no se asignaron. Entonces ${#a[@]}(igual ${#a}que en ksh es el tamaño del elemento del índice 0) es el número de elementos en la matriz y el índice asignado más grande.
- matrices asociativas son compatibles.
- Se admite una gran cantidad de operadores para trabajar con matrices, demasiado grande para enumerar aquí.
- matrices definidas como
a=(x y). set -A a x ytambién funciona, pero set -A a -- x yno es compatible a menos que en la emulación ksh ( --no se necesita en la emulación zsh).
ksh93. (Aquí se describen las últimas versiones). ksh93, considerado experimental durante mucho tiempo, ahora se puede encontrar en más y más sistemas ahora que se ha lanzado como FOSS. Por ejemplo, es el /bin/sh(donde reemplazó el shell Bourne /usr/xpg4/bin/sh, el shell POSIX todavía se basa en ksh88) y kshde Solaris 11. Sus matrices amplían y mejoran los ksh88.
a=(x y)se puede usar para definir una matriz, pero como a=(...)también se usa para definir variables compuestas ( a=(foo=bar bar=baz)), a=()es ambigua y declara una variable compuesta, no una matriz.
- Las matrices son multidimensionales (
a=((0 1) (0 2))) y los elementos de la matriz también pueden ser variables compuestas ( a=((a b) (c=d d=f)); echo "${a[1].c}").
- Se
a=([2]=foo [5]=bar)puede usar una sintaxis para definir matrices dispersas a la vez.
- Limitaciones de tamaño levantadas.
- No en la medida de
zsh, pero gran cantidad de operadores soportados también para manipular matrices.
"${!a[@]}" para recuperar la lista de índices de matriz.
- Las matrices asociativas también se admiten como un tipo separado.
bash. bashes la cáscara del proyecto GNU. Se usa como shen versiones recientes de OS / X y algunas distribuciones de GNU / Linux. bashLas matrices emulan principalmente ksh88las que tienen algunas características de ksh93y zsh.
a=(x y)soportado. set -A a x y No es compatible. a=()crea una matriz vacía (sin variables compuestas bash).
"${!a[@]}" para la lista de índices.
a=([foo]=bar)sintaxis compatible, así como algunos otros de ksh93y zsh.
- Las
bashversiones recientes también admiten matrices asociativas como un tipo separado.
yash. Es una implementación POSIX sh relativamente reciente, limpia y con reconocimiento de varios bytes. No en uso amplio. Sus matrices son otra API limpia similar azsh
- las matrices no son escasas
- Los índices de matriz comienzan en 1
- definido (y declarado) con
a=(var value)
- elementos insertados, eliminados o modificados con el
arrayincorporado
array -s a 5 valuepara modificar el 5 º elemento fallaría si ese elemento no fue asignado de antemano.
- el número de elementos en la matriz es
${a[#]}, ${#a[@]}siendo el tamaño de los elementos como una lista.
- Las matrices son un tipo separado. Debe
a=("$a")redefinir una variable escalar como una matriz antes de poder agregar o modificar elementos.
- Las matrices no son compatibles cuando se invoca como
sh.
Entonces, a partir de eso, puede ver que la detección de soporte de matriz, que podría hacer con:
if (unset a; set -A a a; eval "a=(a b)"; eval '[ -n "${a[1]}" ]'
) > /dev/null 2>&1
then
array_supported=true
else
array_supported=false
fi
no es suficiente para poder usar esas matrices. Debería definir comandos de envoltura para asignar matrices como elementos completos e individuales, y asegurarse de no intentar crear matrices dispersas.
Me gusta
unset a
array_elements() { eval "REPLY=\"\${#$1[@]}\""; }
if (set -A a -- a) 2> /dev/null; then
set -A a -- a b
case ${a[0]}${a[1]} in
--) set_array() { eval "shift; set -A $1"' "$@"'; }
set_array_element() { eval "$1[1+(\$2)]=\$3"; }
first_indice=0;;
a) set_array() { eval "shift; set -A $1"' -- "$@"'; }
set_array_element() { eval "$1[1+(\$2)]=\$3"; }
first_indice=1;;
--a) set_array() { eval "shift; set -A $1"' "$@"'; }
set_array_element() { eval "$1[\$2]=\$3"; }
first_indice=0;;
ab) set_array() { eval "shift; set -A $1"' -- "$@"'; }
set_array_element() { eval "$1[\$2]=\$3"; }
first_indice=0;;
esac
elif (eval 'a[5]=x') 2> /dev/null; then
set_array() { eval "shift; $1=("'"$@")'; }
set_array_element() { eval "$1[\$2]=\$3"; }
first_indice=0
elif (eval 'a=(x) && array -s a 1 y && [ "${a[1]}" = y ]') 2> /dev/null; then
set_array() { eval "shift; $1=("'"$@")'; }
set_array_element() {
eval "
$1=(\${$1+\"\${$1[@]}"'"})
while [ "$(($2))" -ge "${'"$1"'[#]}" ]; do
array -i "$1" "$2" ""
done'
array -s -- "$1" "$((1+$2))" "$3"
}
array_elements() { eval "REPLY=\${$1[#]}"; }
first_indice=1
else
echo >&2 "Array not supported"
fi
Y luego se accede a elementos de la matriz con "${a[$first_indice+n]}", toda la lista con "${a[@]}"y utilizar las funciones de contenedor ( array_elements, set_array, set_array_element) para obtener el número de elementos de un array (en $REPLY), establecer la matriz como enteros o asignar un elementos individuales.
Probablemente no valga la pena el esfuerzo. Que haría uso perlo límite a la matriz shell Bourne / POSIX: "$@".
Si la intención es que el shell interactivo de un usuario obtenga algún archivo para definir funciones que utilizan arrays internamente, aquí hay algunas notas más que pueden ser útiles.
Puede configurar las zshmatrices para que se parezcan más a las kshmatrices en ámbitos locales (en funciones o funciones anónimas).
myfunction() {
[ -z "$ZSH_VERSION" ] || setopt localoption ksharrays
# use arrays of indice 0 in this function
}
También puede emular ksh(mejorar la compatibilidad con kshmatrices y varias otras áreas) con:
myfunction() {
[ -z "$ZSH_VERSION" ] || emulate -L ksh
# ksh code more likely to work here
}
Con esto en mente y que está dispuesto a soltar para yashy ksh88y versiones anteriores de pdkshderivados, y siempre y cuando no se intenta crear matrices dispersas, que deben ser capaces de utilizar de manera uniforme:
a[0]=foo
a=(foo bar)(pero no a=())
"${a[#]}"` "${a[@]}"`"${a[0]}"
en aquellas funciones que tienen emulate -L ksh, mientras el zshusuario todavía usa sus matrices normalmente de la manera zsh.