Estou lendo o " Guia Bash para Iniciantes ". Diz:
Se o primeiro caractere de
PARAMETER
for um ponto de exclamação, o Bash usará o valor da variável formado a partir do restante dePARAMETER
como o nome da variável; essa variável é então expandida e esse valor é usado no resto da substituição, ao invés do valor emPARAMETER
si. Isso é conhecido como expansão indireta.
O exemplo dado é:
franky ~> echo ${!N*}
NNTPPORT NNTPSERVER NPX_PLUGIN_PATH
Não entendo muito bem aqui:
o valor da variável formada a partir do resto de
PARAMETER
Como PARAMETER
é justo !N*
, então
o resto de
PARAMETER
é justo N*
. Como isso pode formar uma variável? Bash pesquisou todos os comandos possíveis lá?
fonte
Parece haver uma exceção quando a "indireção" fornecida termina em a
*
, como acontece aqui. Nesse caso, ele fornece todos os nomes de variáveis que começam com a parte que você especificou (N
aqui). O Bash pode fazer isso porque rastreia variáveis e sabe quais existem.A verdadeira indireção é esta:
digamos que eu tenha uma variável
$VARIABLE
definida como42
e outra variável$NAME
definida comoVARIABLE
.${!NAME}
vai me dar42
. Você usa o valor de uma variável para informar o nome de outra:$ NAME="VARIABLE" $ VARIABLE=42 $ echo ${!NAME} 42
fonte
Sim, ele procura todas as expansões possíveis de variáveis após!. Se você tivesse feito:
echo ${!NP*}
você obteria apenas
NPX_PLUGIN_PATH
.Considere o seguinte exemplo:
:~> export myVar="hi" :~> echo ${!my*} myVar :~> export ${!my*}="bye" :~> echo $myVar bye
fonte
${!my*}
expandir para myA, myB, myA é exportado com seu valor atual e myB é definido como "bye" e exportado. Não é muito útil.Você atingiu uma exceção no processamento indireto, onde se o último caractere for
*
, todas as variáveis que têm o prefixo fornecido antes serão retornadas.fonte
*
caso, é o mesmo que${${VAR}}
?${${VAR}}
mais abreviadamente gravável como${$VAR}
, não é válido, pois$VAR
retorna uma string, que não pode seguir o$
sinal; para usar uma string como nome de variável, você precisa introduzir um nível de indireção (conforme citado na própria pergunta original), ou seja , você pode usar${!VAR}
, que faz exatamente o que você esperaria (erroneamente, mas compreensivelmente)${$VAR}
faz.Você pode consultar este documento GNU para bash para informações oficiais
https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html#Shell-Parameter-Expansion
Mas basicamente, a expansão indireta não é executada
${!prefix*}
como uma das exceções, em seu exemplo, N é o prefixo.O documento explicará o que é expansão indireta em bash
fonte