Listar variáveis com prefixo onde o prefixo é armazenado em outra variável

5

Estou tentando listar todas as variáveis com um determinado prefixo, mas esse prefixo é determinado dinamicamente. Por exemplo:

prefix=apple_
apple_one=a1
apple_two=a2

Se eu simplesmente fizer:

echo ${!apple_@}

Eu posso obter os nomes das variáveis que começam com apple_. No entanto, eu gostaria de fazer isso usando o prefixo de variável de alguma forma. Tudo que eu tentei leva a uma má substituição. Por exemplo, não posso:

echo ${!${prefix}@}
    
por Angelo 27.11.2015 / 23:34

3 respostas

4

Bash não analisa expansões de variáveis aninhadas. Você pode fazer o que quiser com eval : construa o fragmento de shell ${!apple_@} e use-o em um comando executado com eval .

prefix=apple_
eval 'vars=(${!'"$prefix"'@})'

Certifique-se de que prefix contenha apenas caracteres identificadores válidos, caso contrário, o snippet pode resultar em qualquer coisa.

eval é normalmente necessário para trabalhar com variáveis cujo nome é calculado dinamicamente, mas neste caso específico há uma maneira completamente diferente de fazer a mesma coisa: use o sistema de conclusão. O sistema de conclusão do Bash funciona até mesmo de um script. O compgen incorporado lista uma conclusão por linha, o que é ambíguo quando as conclusões podem conter novas linhas, mas esse não é o caso aqui - elas nem contêm caracteres curinga, portanto, a saída pode ser dividida com uma expansão simples sem aspas. Isso não produzirá nada com segurança se o prefixo contiver caracteres que não são válidos em identificadores.

vars=($(compgen -v "$prefix"))
    
por 28.11.2015 / 00:08
1

Você pode usar env | grep '^prefix' .

Por exemplo:

$ env | grep '^LESS'
LESSBINFMT=*u.
LESS=-MMqx4ij3
LESSOPEN=| /usr/bin/lesspipe %s
LESSCLOSE=/usr/bin/lesspipe %s %s

Se você quer apenas os valores e não os nomes das variáveis, use o awk:

$ env | awk -F= '/^LESS/ {print $2}'
*u.
-MMqx4ij3
| /usr/bin/lesspipe %s
/usr/bin/lesspipe %s %s

(ou imprima $ 1 apenas para os nomes das variáveis)

    
por 27.11.2015 / 23:40
0
preset(){
    eval "printf %b $(#"
          set -- "${1##[0-9]*}" _\[:alnum:]
          [ -z   "${1##*[!$2]*}"  ]|| set |
          sed -ne"s/^\($1[$2]*\)=.*/"'"${+\n}" \/p')
"; }; #"

apple_one="a single apple"
apple_two="an apple and an
apple_three='is not actually set at all'
"

preset apple_
apple_one
apple_two
    
por 28.11.2015 / 00:54