Supondo que você deseja restringir a Bourne como conchas (muitas outras escudos como csh
, tcsh
, rc
, es
ou fish
matrizes de apoio, mas escrever um script compatível ao mesmo tempo para Bourne-como conchas e aqueles é complicado e geralmente inútil como eles são intérpretes para completamente diferente e idiomas incompatíveis), observe que existem diferenças significativas entre as implementações.
Os Bourne como conchas que suportam matrizes são:
ksh88
(esse é o primeiro a implementar matrizes, o ksh88 ainda é encontrado como ksh
nos escritórios comerciais mais tradicionais, onde também é a base sh
)
- matrizes são unidimensionais
- As matrizes são definidas como
set -A array foo bar
ou set -A array -- "$var" ...
se você não pode garantir que $var
não começará com um -
ou +
.
- Os índices da matriz começam em
0
.
- Elementos de matriz individuais são atribuídos como
a[1]=value
.
- matrizes são esparsas. Ou seja
a[5]=foo
, funcionará mesmo se a[0,1,2,3,4]
não estiver definido e os deixará desativados.
${a[5]}
para acessar o elemento do índice 5 (não necessariamente o sexto elemento se a matriz for escassa). O 5
que pode haver qualquer expressão aritmética.
- o tamanho e o índice da matriz são limitados (a 4096).
${#a[@]}
é o número do elemento designado na matriz (não o maior índice atribuído).
- não há como conhecer a lista de subscritos atribuídos (além de testar individualmente os 4096 elementos
[[ -n "${a[i]+set}" ]]
).
$a
é o mesmo que ${a[0]}
. Ou seja, matrizes de alguma forma estendem variáveis escalares, dando-lhes valores extras.
pdksh
e derivativos (essa é a base para ksh
e, às vezes, sh
vários BSDs e foi a única implementação do ksh de código aberto antes da liberação do código do ksh93):
Principalmente como ksh88
mas note:
- Algumas implementações antigas não eram compatíveis
set -A array -- foo bar
( --
não eram necessárias lá).
${#a[@]}
é um mais o índice do maior índice atribuído. ( a[1000]=1; echo "${#a[@]}"
gera 1001 mesmo que a matriz tenha apenas um elemento.
- nas versões mais recentes, o tamanho da matriz não é mais limitado (exceto pelo tamanho dos números inteiros).
- versões recentes de
mksh
ter alguns operadores extras inspirados bash
, ksh93
ou zsh
como atribuições a la a=(x y)
, a+=(z)
, ${!a[@]}
para obter a lista de índices atribuídos.
zsh
. zsh
matrizes geralmente são melhor projetadas e tiram o melhor de ksh
e csh
matrizes. Eles são semelhantes, ksh
mas com diferenças significativas:
- índices começam em 1, não em 0 (exceto
ksh
emulação), que é consistente com a matriz Bourne (os parâmetros de posição $ @, que zsh
também expõe como sua matriz $ argv) e csh
matrizes.
- eles são um tipo separado das variáveis normais / escalares. Os operadores se aplicam de maneira diferente a eles e como você geralmente espera.
$a
não é o mesmo que, ${a[0]}
mas se expande para os elementos não vazios da matriz ( "${a[@]}"
para todos os elementos como em ksh
).
- eles são matrizes normais, não matrizes esparsas.
a[5]=1
funciona, mas atribui todos os elementos de 1 a 4 a sequência vazia, se eles não foram atribuídos. Então ${#a[@]}
(o mesmo ${#a}
que em ksh é o tamanho do elemento do índice 0) é o número de elementos na matriz e o maior índice atribuído.
- matrizes associativas são suportadas.
- um grande número de operadores para trabalhar com matrizes é suportado, grande demais para listar aqui.
- matrizes definidas como
a=(x y)
. set -A a x y
também funciona, mas set -A a -- x y
não é suportado, exceto na emulação ksh ( --
não é necessária na emulação zsh).
ksh93
. (aqui descrevendo as versões mais recentes). ksh93
, considerados há muito experimentais, agora podem ser encontrados em mais e mais sistemas, agora que foram lançados como FOSS. Por exemplo, é o /bin/sh
(onde substituiu o shell Bourne, /usr/xpg4/bin/sh
o shell POSIX ainda se baseia ksh88
) e ksh
de Solaris 11
. Suas matrizes estendem e aprimoram o ksh88.
a=(x y)
pode ser usado para definir uma matriz, mas como a=(...)
também é usado para definir variáveis compostas ( a=(foo=bar bar=baz)
), a=()
é ambíguo e declara uma variável composta, não uma matriz.
- matrizes são multidimensionais (
a=((0 1) (0 2))
) e elementos de matriz também podem ser variáveis compostas ( a=((a b) (c=d d=f)); echo "${a[1].c}"
).
- Uma
a=([2]=foo [5]=bar)
sintaxe pode ser usada para definir matrizes esparsas de uma só vez.
- Limitações de tamanho levantadas.
- Não na extensão de
zsh
, mas um grande número de operadores suportados também para manipular matrizes.
"${!a[@]}"
para recuperar a lista de índices da matriz.
- matrizes associativas também suportadas como um tipo separado.
bash
. bash
é o shell do projeto GNU. É usado como sh
nas versões recentes do OS / X e em algumas distribuições GNU / Linux. bash
matrizes emulam principalmente ksh88
aquelas com alguns recursos de ksh93
e zsh
.
a=(x y)
suportado. set -A a x y
não suportado. a=()
cria uma matriz vazia (sem variáveis compostas bash
).
"${!a[@]}"
para a lista de índices.
a=([foo]=bar)
sintaxe suportada, bem como algumas outras de ksh93
e zsh
.
bash
versões recentes também suportam matrizes associativas como um tipo separado.
yash
. É uma implementação POSIX sh relativamente recente, limpa e com reconhecimento de vários bytes. Não é amplamente utilizado. Suas matrizes são outra API limpa semelhante azsh
- matrizes não são esparsas
- Os índices de matriz começam em 1
- definido (e declarado) com
a=(var value)
- elementos inseridos, deletados ou modificados com o
array
embutido
array -s a 5 value
para modificar o 5 th elemento iria falhar se esse elemento não foi atribuído anteriormente.
- o número de elementos na matriz é
${a[#]}
, ${#a[@]}
sendo o tamanho dos elementos como uma lista.
- matrizes são um tipo separado. Você precisa
a=("$a")
redefinir uma variável escalar como uma matriz antes de poder adicionar ou modificar elementos.
- matrizes não são suportadas quando chamadas como
sh
.
Então, a partir disso, você pode ver a detecção de suporte à matriz, o que você poderia fazer com:
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
não é suficiente para poder usar essas matrizes. Você precisaria definir comandos de wrapper para atribuir matrizes como um todo e elementos individuais e certifique-se de não tentar criar matrizes esparsas.
Gostar
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
E então você acessar os elementos de matriz com "${a[$first_indice+n]}"
, toda a lista com "${a[@]}"
e usar as funções de mensagens publicitárias ( array_elements
, set_array
, set_array_element
) para obter o número de elementos de um array (em $REPLY
), definir a matriz como um todo ou atribuir um elementos individuais.
Provavelmente não vale o esforço. Eu usaria perl
ou limite para a matriz shell Bourne / POSIX: "$@"
.
Se a intenção é ter algum arquivo a ser obtido pelo shell interativo de um usuário para definir funções que usam internamente matrizes, aqui estão mais algumas notas que podem ser úteis.
Você pode configurar zsh
matrizes para se ksh
parecerem com matrizes em escopos locais (em funções ou funções anônimas).
myfunction() {
[ -z "$ZSH_VERSION" ] || setopt localoption ksharrays
# use arrays of indice 0 in this function
}
Você também pode emular ksh
(melhorar a compatibilidade com ksh
matrizes e várias outras áreas) com:
myfunction() {
[ -z "$ZSH_VERSION" ] || emulate -L ksh
# ksh code more likely to work here
}
Com isso em mente e você está disposto a perder o suporte para yash
e ksh88
e versões mais antigas do pdksh
derivados, e contanto que você não tente criar matrizes esparsas, você deve ser capaz de usar de forma consistente:
a[0]=foo
a=(foo bar)
(mas não a=()
)
"${a[#]}"
, "${a[@]}"
,"${a[0]}"
naquelas funções que possuem emulate -L ksh
, enquanto o zsh
usuário ainda usa suas matrizes normalmente da maneira zsh.