Usando bash expansão do parâmetro :
$ foobar_1=x foobar_2=y foobar_3=z
$ for v in "${!foobar_@}"; do echo "$v"; done
Saída:
foobar_1
foobar_2
foobar_3
'dereference':
$ for v in "${!foobar_@}"; do echo "${!v}"; done
Saída²:
x
y
z
Eu preciso expandir alguns nomes de variáveis de shell (não de ambiente) que estão relacionados tematicamente, por exemplo, B2_...
onde ...
pode ser uma ou mais coisas diferentes, como ACCOUNT_ID
, ACCOUNT_KEY
, RESPOSITORY
e assim por diante.
Eu não sei com antecedência quantas variáveis existem nem quais são. É isso que eu quero descobrir.
Eu quero poder percorrer as variáveis B2...
sem precisar colocar cada nome individual na lista, de forma semelhante a como eu faria as expansões de nome de arquivo glob.
Eu uso o zsh para sessões interativas, mas as soluções para sh ou bash também são boas.
Usando bash expansão do parâmetro :
$ foobar_1=x foobar_2=y foobar_3=z
$ for v in "${!foobar_@}"; do echo "$v"; done
foobar_1
foobar_2
foobar_3
$ for v in "${!foobar_@}"; do echo "${!v}"; done
x
y
z
Em vez de usar variáveis individuais com nomes que começam com B2_
, você pode usar uma matriz associativa ( B2
). por exemplo,
Observação: o seguinte é específico para zsh
. ksh
e bash
também possuem matrizes associativas, mas a sintaxe para inicializá-las e usá-las é diferente (veja abaixo).
typeset -A B2
# initialise array
B2=(ACCOUNT_ID 12345 ACCOUNT_KEY 54321 REPOSITORY somewhere)
# two different ways of adding elements to the array
B2[FOO]=bar
B2+=(NAME fred)
for key val in ${(kv)B2}; do
echo "$key: $val"
done
A saída para esse exemplo seria:
ACCOUNT_KEY: 54321
FOO: bar
REPOSITORY: somewhere
ACCOUNT_ID: 12345
NAME: fred
Você também pode imprimir a matriz inteira (em um formulário adequado para reutilização em um script ou na linha de comando) com typeset -p
:
% typeset -p B2
typeset -A B2=( ACCOUNT_ID 12345 ACCOUNT_KEY 54321 FOO bar NAME fred REPOSITORY somewhere )
As mesmas operações em ksh
ou Bash seriam as seguintes:
# initialise it
typeset -A B2
B2=([ACCOUNT_ID]=12345 [ACCOUNT_KEY]=54321 [REPOSITORY]=somewhere)
# add elements
B2[FOO]=bar
B2+=([NAME]=fred)
# get a list of the keys and use them as indexes to get the values
for key in "${!B2[@]}"; do
echo "$key: ${B2[$key]}"
done
# print the entire array
typeset -p B2
compgen -v
. No Bash, você pode listar nomes de variáveis que começam com B2
usando:
compgen -v B2
A execução do comando compgen -v text
lista as mesmas variáveis que estão disponíveis como resultados de preenchimento automático quando você digita $
seguido por text
e, em seguida, pressione a guia. (Você pode ter que pressionar a guia várias vezes para que todas sejam exibidas.) Você pode usar compgen -v
interativamente, mas também pode usá-la em um script. Por exemplo:
$ bash -c 'compgen -v SDK'
SDKMAN_CANDIDATES_DIR
SDKMAN_CURRENT_API
SDKMAN_DIR
SDKMAN_LEGACY_API
SDKMAN_PLATFORM
SDKMAN_VERSION
(O script pode, é claro, estar em um arquivo, em vez de passar para bash
como um operando para o sinal -c
.)
A finalidade de compgen
é executar as conclusões do comando. Veja a saída de help compgen
(no Bash) para informações gerais sobre isso. Embora isso provavelmente faça o que você deseja, você pode descobrir que outras abordagens, como a técnica de expansão de parâmetros na resposta de Gilles Quenot , expresse mais claramente o que você está fazendo. Eu não posso dizer qual é o melhor, pois isso depende do que você está fazendo e talvez também de suas preferências pessoais.
com zsh
:
for var (${(M)${(k)parameters}:#B2_*})
printf '$%s == %s\n' $var ${(P)var}
${(k)parameters}
são as chaves da matriz associativa especial $parameters
que fornece informações sobre todos os parâmetros. ${array:#B2_*}
remove da expansão $array
, os elementos que correspondem a B2_*
. Com (M)
(para M
atched), isso é revertido: mantenha os elementos correspondentes. ${(P)var}
(semelhante a bash
' ${!var}
): expande para o valor do parâmetro cujo nome está armazenado em $var
. Se você deseja apenas as variáveis que não são exportadas:
setopt extendedglob # for ^
for var (${(M)${(k)parameters[(R)^*export*]}:#B2_*})
printf '$%s == %s\n' $var ${(P)var}