Use uma referência de variável “dentro” de outra variável

20

Tenho certeza de que é relativamente simples, só não sei como fazer isso.

#!/usr/bin/ksh
set 'iostat'
myvar=6

Eu quero algo como echo ${$myvar} que eu quero interpretado como ${$myvar} - > ${6} - > value

    
por Brandon Kreisel 22.06.2012 / 22:54

4 respostas

23

Você pode fazer esse tipo de coisa com eval , embutido em muitos shells, incluindo ksh:

#!/usr/bin/ksh
set $(iostat)
myvar=6
eval "echo \$$myvar"

O truque é citar duas vezes a string que você alimenta para eval , de modo que $ myvar seja substituído por "6" e inverter o sinal de dólar externo, para que eval obtenha uma string "$ 6".

Eu tenho "% user" para a saída, mas tentei em uma máquina RHEL com vários processadores.

    
por 22.06.2012 / 23:08
21

Referência indireta a variáveis

Os avançados avançados modernos têm um método para referenciar o valor de uma variável cujo nome é armazenado em outra variável. Infelizmente, o método difere entre ksh, bash e zsh.

Em mksh ≥R39b, você pode fazer myvar a nameref:

typeset -n myvar=6
echo "$myvar"

Isso não funciona no ATT ksh93 porque não suporta namerefs para parâmetros posicionais. No caso de você ter uma variável contendo um nome de variável, você pode usar este método.

foo=bar
typeset -n myvar=foo
echo "$myvar"  # prints bar

No bash ≥2.0, você pode escrever

echo "${!myvar}"

No zsh, você pode escrever

echo ${(P)myvar}

Em shells antigos, incluindo ksh88 e pdksh, seu único recurso quando você tem uma variável contendo outro nome de variável e deseja usar o valor dessa variável eval , como explicado por Bruce Ediger . Esta solução funciona em qualquer shell Bourne / POSIX.

eval "value=\${$myvar}"
echo "$value"

Usando uma matriz

Este é o melhor método aqui: é mais simples e mais portátil.

Para seu caso de uso, em qualquer shell com matrizes (todas as variantes de ksh, bash ≥2.0, zsh), você pode atribuir a uma variável de matriz e obter o elemento que deseja. Esteja ciente de que os arrays ksh e bash começam a numeração em 0, mas o zsh começa em 1, a menos que você emita setopt ksh_arrays ou emulate ksh .

set -A iostat -- $(iostat)
echo "${iostat[5]}"

Se você deseja copiar os parâmetros posicionais para uma variável de matriz a :

set -A a -- "$@"

Em ksh93, mksh ≥R39b, bash ≥2.0 e zsh, você pode usar a sintaxe de atribuição de matriz:

iostat=($(iostat))
echo "${iostat[5]}"
    
por 23.06.2012 / 02:15
1

Como indicado por Gilles (que forneceu a parte bash da resposta), também não invalidando Bruce Ediger's (sobre como fazer isso portável com eval ), veja como fazer isso com nameref em% recentemksh (e AT & T ksh93, exceto - como @Gilles comentou - namerefs não pode se referir a parâmetros posicionais em AT & T ksh, apenas para parâmetros nomeados):

#!/bin/mksh
set -- $(iostat)
nameref myvar=6
echo $myvar

Também adicionamos -- após set para melhorar a resistência.

    
por 27.02.2014 / 14:59
0

Outro uso de matrizes

Não usei ksh ou qualquer variante por algum tempo, então não tenho certeza se o ksh (ou bash) tem uma capacidade similar. Meu shell principal é zsh. Eu uso arrays ao manipular a saída de comandos como iostat porque eles produzem várias linhas, e nem todas as linhas são do mesmo formato / comprimento.

#! /bin/zsh
IOStatOutput=("${(@f)$(iostat)}") # Produces one element per line

O acima também ignora o uso de parâmetros posicionais. Agora, se você quiser gerar, digamos, uma matriz de dispositivos:

for Element in {7..${#IOStatOutput}} # Devices listed in elements 7 thru the last
do
    DevList+=( ${${=IOStatOutput[Element]}[1]} )
done

Acho os pedaços menores muito mais fáceis de manusear. Você pode ou não precisar usar referência de variável indireta, dependendo do seu código. Saber como funciona ainda é bom saber. Eu uso eu mesmo.

    
por 13.03.2014 / 10:45