Existe uma maneira concisa de testar o suporte de matriz pelo shell local semelhante a Bourne na linha de comando?
Isso é sempre possível:
$ arr=(0 1 2 3);if [ "${arr[2]}" != 2 ];then echo "No array support";fi
ou teste $SHELL
e versão do shell:
$ eval $(echo "$SHELL --version") | grep version
e depois lendo a página de manual, assumindo que eu tenho acesso a ela. (Mesmo lá, escrevendo a partir de /bin/bash
, estou assumindo que todas as conchas semelhantes a Bourne admitem a opção longa --version
, quando isso ocorre por ksh, por exemplo ).
Estou procurando um teste simples que possa ser autônomo e incorporado em uma seção de Uso no início do script ou mesmo antes de chamá-lo.
shell-script
shell
array
Cbhihe
fonte
fonte
csh
não é uma casca de bourne.tcsh
não é um quer (écsh
com alguns bugs corrigidos)$SHELL
é o shell preferido do usuário, como$EDITOR
é o seu editor de texto preferido. Tem pouco a ver com o shell atualmente em execução.eval
Usar a saída$SHELL --version
como código shell não faz sentido.Respostas:
Supondo que você deseja restringir a Bourne como conchas (muitas outras escudos como
csh
,tcsh
,rc
,es
oufish
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 comoksh
nos escritórios comerciais mais tradicionais, onde também é a basesh
)set -A array foo bar
ouset -A array -- "$var" ...
se você não pode garantir que$var
não começará com um-
ou+
.0
.a[1]=value
.a[5]=foo
, funcionará mesmo sea[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). O5
que pode haver qualquer expressão aritmética.${#a[@]}
é o número do elemento designado na matriz (não o maior índice atribuído).[[ -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 paraksh
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: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.mksh
ter alguns operadores extras inspiradosbash
,ksh93
ouzsh
como atribuições a laa=(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 deksh
ecsh
matrizes. Eles são semelhantes,ksh
mas com diferenças significativas:ksh
emulação), que é consistente com a matriz Bourne (os parâmetros de posição $ @, quezsh
também expõe como sua matriz $ argv) ecsh
matrizes.$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 emksh
).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.a=(x y)
.set -A a x y
também funciona, masset -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 baseiaksh88
) eksh
deSolaris 11
. Suas matrizes estendem e aprimoram o ksh88.a=(x y)
pode ser usado para definir uma matriz, mas comoa=(...)
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.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}"
).a=([2]=foo [5]=bar)
sintaxe pode ser usada para definir matrizes esparsas de uma só vez.zsh
, mas um grande número de operadores suportados também para manipular matrizes."${!a[@]}"
para recuperar a lista de índices da matriz.bash
.bash
é o shell do projeto GNU. É usado comosh
nas versões recentes do OS / X e em algumas distribuições GNU / Linux.bash
matrizes emulam principalmenteksh88
aquelas com alguns recursos deksh93
ezsh
.a=(x y)
suportado.set -A a x y
não suportado.a=()
cria uma matriz vazia (sem variáveis compostasbash
)."${!a[@]}"
para a lista de índices.a=([foo]=bar)
sintaxe suportada, bem como algumas outras deksh93
ezsh
.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
a=(var value)
array
embutidoarray -s a 5 value
para modificar o 5 th elemento iria falhar se esse elemento não foi atribuído anteriormente.${a[#]}
,${#a[@]}
sendo o tamanho dos elementos como uma lista.a=("$a")
redefinir uma variável escalar como uma matriz antes de poder adicionar ou modificar elementos.sh
.Então, a partir disso, você pode ver a detecção de suporte à matriz, o que você poderia fazer com:
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
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 seksh
parecerem com matrizes em escopos locais (em funções ou funções anônimas).Você também pode emular
ksh
(melhorar a compatibilidade comksh
matrizes e várias outras áreas) com:Com isso em mente e você está disposto a perder o suporte para
yash
eksh88
e versões mais antigas dopdksh
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ãoa=()
)"${a[#]}"
,"${a[@]}"
,"${a[0]}"
naquelas funções que possuem
emulate -L ksh
, enquanto ozsh
usuário ainda usa suas matrizes normalmente da maneira zsh.fonte
Você pode usar
eval
para experimentar a sintaxe da matriz:fonte
ksh88
suporta matrizes, mas nãoa=()
. Emksh93
,a=()
declara uma variável composta, não uma matriz, a menos que a variável tenha sido declarada anteriormente como uma matriz.yash
, você não faza[5]=1
masarray -s a 5 1
ksh93
composta me surpreendeu, você se importaria em me dar parte da documentação sobre isso? Eu adiciono1
à matriz para fazê-la funcionar.