No Bourne como shell, que suporta variáveis de matriz, podemos usar algumas análises para verificar se a variável é uma matriz.
Todos os comandos abaixo foram executados após a execução 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
e seu derivado:
$ 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
Um exemplo em bash
:
if declare -p var 2>/dev/null | grep -q 'declare -a'; then
echo array variable
fi
Essa abordagem é muito trabalhosa e precisa gerar um subshell. O uso de outro shell embutido como =~
no [[ ... ]]
não precisa de um subshell, mas ainda é muito complicado.
Existe uma maneira mais fácil de realizar essa tarefa?
Respostas:
Eu não acho que você pode, e não acho que isso faça alguma diferença.
Isso faz a mesma coisa em qualquer um de
ksh93
ebash
. Parece que possivelmente todas as variáveis são matrizes nessas shells, ou pelo menos qualquer variável regular que não tenha sido atribuída a atributos especiais, mas eu não verifiquei muito disso.O
bash
manual fala sobre comportamentos diferentes para uma matriz versus uma variável de seqüência de caracteres ao usar+=
atribuições, mas depois faz hedge e afirma que a matriz se comporta apenas de maneira diferente em um contexto de atribuição composto .Ele também afirma que uma variável é considerada uma matriz se algum valor tiver sido atribuído a um índice - e inclui explicitamente a possibilidade de uma sequência nula. Acima, você pode ver que uma tarefa regular definitivamente resulta em um índice subscrito - e, portanto, acho que tudo é uma matriz.
Praticamente, possivelmente você pode usar:
... para identificar claramente as variáveis de conjunto às quais foi atribuído apenas um único índice de valor 0.
fonte
${a[1]-not array}
pode fazer a tarefa, não é?bash
manual: Uma variável de matriz é considerada definida se um valor subscrito tiver sido atribuído. A cadeia nula é um valor válido. Se qualquer subscrito é atribuído, é uma matriz por especificação. Na prática, também não, porque você pode fazera[5]=x
. Eu acho que[ 1 -eq "${#a[@]}" ] && [ -n "${a[0]+1}" ]
poderia funcionar.Então você quer efetivamente apenas a parte do meio ou
declare -p
sem o lixo ao seu redor?Você pode escrever uma macro como:
para que você possa fazer:
(Uma mera função não funcionará se você desejar usá-lo em variáveis de função local).
Com aliases
fonte
alias vartype="$VARTYPE"
... ou simplesmente não defini$VARTYPE
nada - deve funcionar, certo? você só precisa dessashopt
coisabash
porque ela quebra com as especificações relacionadas àalias
expansão nos scripts.No zsh
fonte
echo ${(t)var}
seja mais simples. Obrigado por isso.Para testar a variável var, com
É possível testar se há mais de um índice de matriz:
Se o primeiro valor do índice não for zero:
A única confusão é quando há apenas um valor de índice e esse valor é zero (ou um).
Para essa condição, é possível usar um efeito colateral ao tentar remover um elemento da matriz de uma variável que não é uma matriz:
Isso funciona corretamente para o bash:
Para zsh, o índice pode precisar ser 1 (a menos que um modo compatível esteja ativo).
O sub-shell é necessário para evitar o efeito colateral de apagar o índice 0 de var.
Não encontrei nenhuma maneira de fazê-lo funcionar em ksh.
Editar 1
Esta função funciona apenas no bash4.2 +
Editar 2
Isso também funciona apenas para o bash4.2 +
Nota: Isso fornecerá falsos positivos se var contiver as strings testadas.
fonte
( unset "var[0]" 2>/dev/null; ) && echo "var is an array."
relata corretamente var é uma matriz quando var foi definida comovar=()
uma matriz com zero elementos. Ele age exatamente igual a declarar.grep -E
vez degrep -P
evitar a dependência do GNU grep.-a
, como este:declare -airl var='()'
. Portanto, o teste grep funcionará .Para o bash , é um pouco complicado (embora documentado): tente usar
typeset
para remover o atributo "array":(Você não pode fazer isso
zsh
, pois permite converter uma matriz em um escalar,bash
pois é explicitamente proibido.)Então:
Ou em uma função, observando as advertências no final:
Observe o uso de
typeset -g
(bash-4.2 ou posterior), isso é necessário em uma função para quetypeset
(syn.declare
) Não funcione comolocal
e derrube o valor que você está tentando inspecionar. Isso também não lida com os tipos de "variáveis" da função, você pode adicionar outro teste de ramificação usando,typeset -f
se necessário.Outra opção (quase completa) é usar isso:
Há um pequeno problema, porém, uma matriz com um único índice subscrito de 0 corresponde a duas das condições acima. Isso é algo que o mikeserv também faz referência, o bash realmente não tem uma distinção difícil, e parte disso (se você verificar o Changelog) pode ser atribuída ao ksh e à compatibilidade com como
${name[*]}
ou${name[@]}
se comportar em um não array.Portanto, uma solução parcial é:
Eu usei no passado uma variação sobre isso:
isso também precisa de um subshell.
Uma técnica possivelmente mais útil é
compgen
:Isso listará todas as matrizes indexadas, no entanto, matrizes associativas não são tratadas especialmente (até o bash-4.4) e aparecem como variáveis regulares (
compgen -A variable
)fonte
typeset +a
também relata um erro no ksh. Não no zsh, no entanto.Resposta curta:
Para os dois shells que introduziram essa notação (
bash
eksh93
), uma variável escalar é apenas uma matriz com um único elemento .Nem precisa de uma declaração especial para criar uma matriz. Apenas a tarefa é suficiente, e uma tarefa simples
var=value
é idêntica avar[0]=value
.fonte
bash -c 'unset var; var=foo; typeset -p var'
. O resposta do bash relata uma matriz (precisa de um -a) ?. Agora compare com:bash -c 'unset var; var[12]=foo; typeset -p var'
. Por que há uma diferença? R: O shell mantém (para o bem ou para o mal) uma noção de quais vars são escalares ou matrizes. O shell ksh combina ambos os conceitos em um.O yash's
array
builtin possui algumas opções que funcionam apenas com variáveis de array. Exemplo: a-d
opção relatará um erro na variável que não é da matriz:Para que possamos fazer algo assim:
Essa abordagem não funcionará se a variável da matriz for somente leitura . Tentando modificar uma variável somente leitura levando a um erro:
fonte
fonte