UNIX KSH / BASH Chamada por referência usando Array (no GNU bash 4.2)

1

Sou novo no shell script do Unix Meu código é o seguinte:

  i=0
for var in 'a' 'b' 'c' 'd' 'e'
do
  content[i]=var
  ((i='expr i+1'))
done
a=10
b=50
c=40
d=90
e=100
Now I wanted to print the local variables contents using array into the function

print_array
{
echo "${content[0]}"
echo "${content[1]}"
echo "${content[2]}"
echo "${content[3]}"
echo "${content[4]}"
} 

o que eu quero fazer é que o conteúdo da matriz seja {a, b, c, d, e} e há variáveis locais chamadas a, b, c, d, e com alguns valores atribuídos Eu queria imprimir essas variáveis locais através do uso de array desde o nome de elemento de matriz e elemento de variável local é o mesmo, então eu tentei chamar por referência, tentando várias combinações de $ e array_names, mas não está funcionando

    
por Aman 07.04.2015 / 11:43

3 respostas

1

Então, vou definir uma função de impressão indireta primeiro ...

_print() while [ "$#" -ne 0 ]
         do    printf '$%s = %d\n' \
                       "$1" "$(($1))"
               shift
         done

Em seguida, configurarei a matriz e incrementarei ...

arr=( a b c d e ); i=0
for var in "${arr[@]}"
do  : "$(($var=(i+=10)))"
done

Agora, o valor de $a é 10 e $b 20 e assim por diante. Por último resta apenas para imprimir ...

_print "${arr[@]}"

... que imprime para stdout ...

$a = 10
$b = 20
$c = 30
$d = 40
$e = 50

Tudo isso funciona devido à maneira como o shell lida com $(( math )) expansões - elas são basicamente eval s. Em uma expansão aritmética, o shell primeiro expande qualquer outra expansão de shell válida antes de tentar fazer as contas - tornando a matemática real sua última ordem de negócios.

Isso significa que, se você fizer isso:

i=a a=10; echo "$(($i))" 

O resultado impresso é 10 porque o shell expande o valor de $i para obter a e, em seguida, avalia esse resultado como uma referência inteira.

O acima funcionará em qualquer shell compatível com POSIX.

Isso significa que eu poderia também ter feito ...

i=10
for var in a b c d e
do  arr[($var=i*${#arr[@]}+i)/i]=$var
done

... para manipular atribuição de matriz, avaliação de índice e $var integer assignation de uma vez porque os colchetes [ index ] de uma matriz shell denominada - em um shell que os suporta - são tratados de maneira idêntica à $(( expansion )) parens de uma expressão matemática.

A execução do código acima, agrupado em ksh -xc , imprime a seguinte saída de depuração para o erro padrão:

+ arr[1]=a
+ arr[2]=b
+ arr[3]=c
+ arr[4]=d
+ arr[5]=e

De lá, posso fazer apenas:

echo "$((${arr[1]}))"
echo "$((a))"

... para imprimir ...

10
10

... porque eles avaliam a mesma coisa em shells que suportam matrizes nomeadas. No entanto, em conchas que não ...

echo 'arr=(a b c d e)' | bash -x
+ arr=(a b c d e)     #bash traces the successful command to stderr
echo 'arr=(a b c d e)' | sh -x
sh: 1: Syntax error: "(" unexpected   #sh traces something else

Portanto, na função _print() eu apenas shift sobre os parâmetros posicionais (que representa um array "$@" do shell verdadeiramente portátil) enquanto houver algum e printf . .

  1. Primeiro, um sinal de cifrão $ .
  2. Em seguida, o valor %s tring armazenado no parâmetro posicional $1 st.
  3. Em seguida, um sinal de = é igual.
  4. E por último o valor armazenado no valor armazenado no meu parâmetro posicional $(($1)) .

Como a função shift s seus argumentos desaparecem, o primeiro parâmetro posicional é constantemente substituído pelo próximo até que a contagem $# de posicionais seja igual a 0 e a função retorne.

Antes de executar a função quando inicializo a matriz e suas variáveis indiretas constituintes que funcionam assim:

  • for var in "${arr[@]}"

    • O shell expandirá [@] para uma lista de argumentos e [*] para uma única concatenação dessa lista. Se a expansão não for citada, poderá também expandir [*] para uma lista - dependendo se há ou não um valor para $IFS quando for feito e como set -f nome a expansão está atualmente configurada - mas se o fizer, provavelmente não o faz da maneira que pretende.
  • : "$(($var=(i+=10)))"

    • Cada valor em ${arr[@]} é atribuído ao valor de $var por sua vez. $(($var=(i+=10))) é então expandido primeiro para o valor em $var como $((a=(i+=10))) e por último de toda a matemática - que primeiro incrementa $i por 10 e depois atribui o valor de $i codificar%.
por 07.04.2015 / 12:14
1

Tente

#i=0
for var in 'a' 'b' 'c' 'd' 'e'
do
  content[${#content[*]}]=$var  # or content[i++]=$var
done
# or just content=( 'a' 'b' 'c' 'd' 'e' )
a=10
b=50
c=40
d=90
e=100
for i in "${#content[@]}"
do
  echo ${!i}
done
    
por 07.04.2015 / 11:56
1

Se eu entendi corretamente, você quer uma indireção no acesso da variável com, por exemplo, bash . Com este código:

content=( a b c d e )

a=10
b=50
c=40
d=90
e=100

echo "${!content[0]}"
echo "${!content[1]}"
echo "${!content[2]}"
echo "${!content[3]}"
echo "${!content[4]}"

Você receberá este resultado:

10
50
40
90
100

A chave aqui é o método específico de acesso à expansão de variáveis bash "${! ... }" .

    
por 07.04.2015 / 13:45