Nomes de variáveis de shell Globbing

5

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.

    
por Nick Coleman 19.03.2018 / 01:30

4 respostas

6

Usando 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
    
por 19.03.2018 / 01:48
5

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
    
por 19.03.2018 / 02:00
4

Bash tem 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.

    
por 19.03.2018 / 02:06
3

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}
    
por 19.03.2018 / 08:12