É possível imprimir o conteúdo do conteúdo de uma variável com script de shell? (referência indireta)

13

Vamos supor que eu tenha declarado as seguintes variáveis:

$ var='$test'
$ test="my string"

Se eu imprimir seu conteúdo, vejo o seguinte:

$ echo $var
$test

$ echo $test
my string

Gostaria de encontrar uma maneira de imprimir o conteúdo do conteúdo de $var (que é o conteúdo de $test ). Então eu tentei fazer o seguinte:

$ echo $(echo $var)
$test

Mas aqui o resultado é $test e não "my string" ... É possível imprimir o conteúdo do conteúdo das variáveis usando o bash?

    
por Rafael Muynarsk 30.06.2018 / 00:38

4 respostas

21

Você pode fazer isso usando a expansão de variável indireta do bash (desde que não seja problema deixar de fora o $ da sua variável de referência):

$ var=test
$ test="my string"
$ echo "$var"
test
$ echo "${!var}"
my string

3.5.3 Expansão do Parâmetro Shell

    
por 30.06.2018 / 00:41
10

Para o caso em que o nome da variável contido em var é prefixado com $ , você pode usar eval :

$ var='$test'
$ test="my string"
$ eval echo $var
my string

O que acontece aqui:

  • o bash expande $var para o valor $test , produzindo um comando eval echo $test ;
  • eval avalia a expressão echo $test e produz um resultado desejado.

Note que usar eval em geral pode ser perigoso (dependendo do que está armazenado em var ), então prefira evitá-lo. O recurso de expansão indireta é melhor para o seu caso (mas você precisa se livrar do $ login em $test ).

    
por 30.06.2018 / 00:48
8

Semelhante a resposta de Jesse_b , mas usando uma variável de referência de nome em vez de indireto de variável (requer bash 4.3 +):

$ declare -n var=test
$ test="my string"
$ echo "$var"
my string

A variável de referência de nome var contém o nome da variável que está referenciando. Quando a variável é desreferenciada como $var , o valor dessa outra variável é retornado.

bash resolve as referências de nome recursivamente:

$ declare -n var1=var2
$ declare -n var2=test
$ test="hello world"
$ echo "$var1"
hello world

Para completar, usar uma matriz associativa (em bash 4.0+) também é uma maneira de resolver isso, dependendo dos requisitos:

$ declare -A strings
$ strings[test]="my string"
$ var=test
$ echo "${strings[$var]}"
my string

Isso fornece uma maneira mais flexível de acessar mais de um valor por uma chave ou nome que pode ser determinado dinamicamente.

    
por 30.06.2018 / 09:11
3

com zsh :

$ var='$test'
$ test='*'
$ printf '%s\n' ${(e)var}
*

Com qualquer shell parecido com o Bourne

$ eval 'printf "%s\n" "'"$var"'"'
*

Lembre-se que nesses shells as expansões de variáveis devem ser citadas para evitar split + glob ( zsh sendo uma exceção) e echo não pode ser usado para dados arbitrários.

Já que com (e) e eval há avaliação de código de shell, é importante que o conteúdo de $var permaneça dentro de seu controle, caso contrário isso pode ser uma vulnerabilidade arbitrária de injeção de comando (mesmo com ${!var} abordagens).

    
por 01.07.2018 / 08:53