Expansão aritmética e expansão de parâmetros

1
$ x=foo; foo=bar; bar=6; 

$ echo $x
foo

$ echo $((x))
6

por que a expansão aritmética pode rastrear da variável x ao seu valor foo , da variável foo ao seu valor bar , e da variável foo ao seu valor 6 , em vez de parar no valor foo de x ?

Parece que a expansão aritmética se aplica eval indefinidamente muitas vezes à expansão de parâmetro da variável x , até atingir um inteiro ou nada?

    
por Tim 24.04.2016 / 04:48

1 resposta

2

Essa é uma extensão de bash (e também zsh , ksh e suas derivadas) para permitir que a variável shell contenha constantes inteiras inválidas para serem reutilizadas na expressão aritmética.

De bash Aritmética da casca :

Shell variables are allowed as operands; parameter expansion is performed before the expression is evaluated. Within an expression, shell variables may also be referenced by name without using the parameter expansion syntax. A shell variable that is null or unset evaluates to 0 when referenced by name without using the parameter expansion syntax. The value of a variable is evaluated as an arithmetic expression when it is referenced, or when a variable which has been given the integer attribute using ‘declare -i’ is assigned a value. A null value evaluates to 0. A shell variable need not have its integer attribute turned on to be used in an expression.

Portanto, no seu caso, $((x)) primeiro expandiu x para foo , que é um inteiro inválido, portanto, foo é reutilizado como uma referência de nome de variável. Em seguida, foo foi expandido para bar , o processo acima foi repetido até você obter 6 , que é um inteiro válido.

A especificação POSIX apenas afirmou que $((x)) e $(($x)) retornarão o mesmo valor somente quando x for uma constante inteira válida. Ele não diz nada sobre o caso x é um inteiro inválido, portanto, as implementações do shell estão livres para lidar com essa situação.

O resultado pode ser variado com diferentes camadas.

zsh , ksh e seus derivados se comportam como bash acima (e também busybox sh ).

ash , dash aumentar erro se x contiver inteiro inválido

$ x=foo foo=bar bar=6 dash -c 'echo "$((x))"'
dash: 1: Illegal number: foo

yash deixa a variável como está:

$ x=foo foo=bar bar=6 yash -c 'echo "$((x))"'
foo
    
por 24.04.2016 / 05:36