Meu objetivo é entender o conceito geral de "atributos variáveis", esperando que isso me ajude a entendero que é declarar no Bash.
O que é um atributo variável? Por que alguém iria querer dar um atributo a uma variável? Por que apenas criar variáveis e expandi-las na execução não é "suficiente" ao trabalhar com variáveis?
Responder1
Normalmente, uma variável é um local para armazenar um valor. Você atribui um valor à variável ( var="some value"
) e depois disso pode recuperar o valor com uma expansão de variável (escrever "$var"
é equivalente a escrever "some value"
).
É possível criar variáveis que façam algo especial quando você atribui um valor a elas ou em outras circunstâncias onde o shell acessa variáveis. Um atributo em uma variável é uma anotação que o shell armazena próximo ao nome e valor da variável, que informa ao shell para aplicar esse comportamento especial.
Um exemplo
declare -i x
informa ao shell que x
deve conter apenas valores inteiros. Normalmente, quando você atribui um valor a uma variável, o shell pega a string resultante da expansão do lado direito do sinal de igual e a armazena como o valor da variável. Mas se a variável tiver o atributo inteiro, o shell analisa essa string como uma expressão aritmética e armazena o resultado da avaliação dessa expressão. Por exemplo:
$ x=2+2; echo $x
2+2
$ declare -i x; x=2+2; echo $x
4
$ declare -i x; x=2+hello; echo $x
2
$ declare -i x; x=2+
bash: 2+: syntax error: operand expected (error token is "+")
(A terceira linha x=2+hello
definida x
como 2 porque hello
é um nome de variável que não está definido, e variáveis não definidas são interpretadas silenciosamente como 0 por padrão.)
Mais exemplos
declare -l var
declara quevar
deve conter apenas letras minúsculas. Quando o shell armazena o valor da variável, ele converte qualquer letra maiúscula em minúscula.declare -u var
faz a conversão na outra direção.declare -r var
tornavar
somente leitura, o que também é um comportamento especial de atribuição: faz com que todas as atribuições subsequentesvar
falhem.declare -x var
faz comvar
que seja exportado para o meio ambiente. Para este atributo, o comportamento especial acontece quando o bash executa um comando externo: comandos externos veem um ambiente que contém as variáveis que o shell está exportando no momento em que o shell executa o comando externo.
Responder2
De help declare
:
Options which set attributes:
-a to make NAMEs indexed arrays (if supported)
-A to make NAMEs associative arrays (if supported)
-i to make NAMEs have the `integer' attribute
-l to convert the value of each NAME to lower case on assignment
-n make NAME a reference to the variable named by its value
-r to make NAMEs readonly
-t to make NAMEs have the `trace' attribute
-u to convert the value of each NAME to upper case on assignment
-x to make NAMEs export
Nota: declare
também pode ser usado para funções.
Cada um desses atributos tem um ou vários usos:
-a
- para criar matrizes indexadas de NAMEs (se suportado)
Isso não é totalmente necessário porque definir um parâmetro como um array irá declará-lo automaticamente como um array indexado. Usar isso pode tornar seu código mais óbvio e legível.
-A
- para criar matrizes associativas de NAMEs (se suportado)
AFAIK, isso é totalmente necessário, pois tentar definir um array associativo sem primeiro declará-lo como tal resultará em um array indexado.
$ assoc=([foo]=bar)
$ declare -p assoc
declare -a assoc=([0]="bar")
$ unset assoc
$ declare -A assoc
$ assoc=([foo]=bar)
$ declare -p assoc
declare -A assoc=([foo]="bar" )
-i
- fazer com que NAMEs tenham o atributo `inteiro'
Útil se você quiser garantir que seu parâmetro possaapenasmantenha números inteiros. Isso também permite realizar expansão aritmética na atribuição.
$ declare -i a
$ a=foo
$ echo $a
0
$ a=1+1
$ echo $a
2
-l
- para converter o valor de cada NOME para minúsculas na atribuição
Garantirá que o valor dos seus parâmetros sempre estará em letras minúsculas. Este é um recurso muito legal que eu não conhecia e provavelmente usarei no futuro. Ele elimina a necessidade de expansão complexa de parâmetros ou de usar um utilitário separado comotr
$ declare -l foo=Bar
$ echo $foo
bar
-n
- faça de NAME uma referência à variável nomeada por seu valor
Como uma referência indireta. Isso poderia eliminar o uso de eval
muitos scripts.
$ a=foo
$ declare -n b=a
$ echo $b
foo
-r
- para tornar NAMEs somente leitura
Este é um bom recurso. Pode ser especialmente útil para variáveis de shell/ambiente que você deseja definir uma vez e garantir que não sejam alteradas
$ declare -r foo=bar
$ echo $foo
bar
$ foo=baz
-bash: foo: readonly variable
-t
- fazer com que NAMEs tenham o atributo `trace'
Não tenho certeza sobre este. Acho que pode se aplicar apenas a funções.
-u
- para converter o valor de cada NOME para letras maiúsculas na atribuição
Semelhante, -l
mas oposto
$ declare -u foo=bAr
$ echo $foo
BAR
-x
- para fazer a exportação de NAMEs
Apenas mais uma forma de exportar variáveis para o ambiente.