Definir variáveis ​​com um nome de variável

11

O que há de errado com esse script? Estou tentando definir A1 = 1, B1 = 1, C1 = 1

LIST="A B C"
for x in $LIST
do
    "$x"1=1
done

e o resultado é:

./x.: line 7: A1=1: command not found
./x.: line 7: B1=1: command not found
./x.: line 7: C1=1: command not found
Ake Blomberg
fonte
1
Eu não acho que você pode criar variáveis ​​no bash assim. É para isso que servem as matrizes.
Jakuje 22/08/2015
3
Use eval "$x"1=1. Embora, como Jakuje observou, as matrizes provavelmente sejam mais adequadas para este caso.
Andrea Corbellini
@AndreaCorbellini Você deve escrever isso como resposta.
Sparhawk

Respostas:

21

Uma atribuição de variável tem a forma de um nome de variável, seguido pelo sinal de igual, seguido pelo valor (opcional).

Esta é uma atribuição válida:

ABC=123

"$x"1=1não é uma atribuição válida, porque "$x"1não é um nome de variável. Pode ser eval uated para um nome de variável, mas não é. O shell, de fato, acredita que é um comando.

Uma maneira de fazer o que você deseja alcançar é o seguinte:

eval "$x"1=1

Outra maneira no bash (mas não em outras conchas) é:

declare "$x"1=1

Ou também (novamente apenas para o bash):

let "$x"1=1

(Não há muita diferença no seu caso.)

Mas, como Jakuje observou nos comentários , você provavelmente deseja usar arrays, se o seu shell os possuir (ksh, bash ou zsh).


Para completar:

  • evalexecuta comandos arbitrários. Portanto, se no lado direito do sinal de igual você tiver uma variável que se expande para algum comando, esse comando será executado. O código a seguir:

    x=a
    y='$(echo hello)'
    eval "$x=$y"

    é equivalente a a=hello.

  • declareé um bash embutido para atribuir variáveis ​​e não executa nenhum comando. O código a seguir:

    x=a
    y='$(echo hello)'
    declare "$x=$y"

    é equivalente a a='$(echo hello)'.

  • leté semelhante ao declarefato de não executar comandos. Mas declare, ao contrário de , letpode ser usado para operações aritméticas:

    let a="1 + 2"

    é equivalente a a=3.

Andrea Corbellini
fonte
Even ABC = 123é inválido. Porque o espaço é adicionado antes e depois do equal(=)sinal.
Mahendran Sakkarai 6/11/19
3

O FAQ do bash tem uma entrada indireta. Na maioria dos casos de uso, o que você realmente deve fazer é usar uma matriz associativa ou indexada. Você também pode usar

func_call_by_reference() { # Bash 4.3
    typeset -n ref=$1   # nameref to the variable named by the caller
    ref=( "val1" "val2" ... )  # return an array by reference
}

Consulte a entrada das Perguntas frequentes para obter mais opções para fazer isso, evitando ainda evalcitações confusas .

Peter Cordes
fonte
0

Você pode usar código como a seguir. No seu código, o shell é executado "$x"1=1como um comando porque não é uma atribuição de variável válida.

LIST="A B C"
for x in $LIST
do
    a=$(echo "$x"1)
    let $a=1
done
AVJ
fonte
Qual shell você está usando? Usando bash Bosh 4.1.7 e 4.3.11 recebo erros sobre command not found <varname>=1quando tento fazer isso (obviamente com o <varname> sendo o valor I armazenada em a)
Eric Renouf
como explicado por @Andrea Corbellini, temos que usar deixar, declarar ou eval ao valor de atribuir ..
AVJ
1
você não precisa echoaqui! Apenas a="$x"1. Também leté um contexto aritmético, portanto, você só pode atribuir números com ele.
Peter Cordes
declare $a=foobartrabalho.
Peter Cordes