bash dynamic (variabel) nama variabel

12

Saya ingin secara dinamis membuat urutan string dengan memanipulasi array elemen dan membuat beberapa prosedur aritmatika.

for name in FIRST SECOND THIRD FOURTH FIFTH; do
    $name = $(( $6 + 1 ))
    $name = "${$name}q;d"
    echo "${$name}"; printf "\n"
done

Hasil keinginan akan menjadi di bawah ini untuk $6sama 0.

1q;d
2q;d
3q;d
4q;d
5q;d

Tapi saya mendapatkan kesalahan ini

reel_first_part.sh: line 18: FIRST: command not found
reel_first_part.sh: line 19: ${$name}q;d: bad substitution
reel_first_part.sh: line 18: FIRST: command not found
reel_first_part.sh: line 19: ${$name}q;d: bad substitution
reel_first_part.sh: line 18: FIRST: command not found
reel_first_part.sh: line 19: ${$name}q;d: bad substitution

Saya kira itu sesuatu yang sederhana. Dulu bekerja ketika saya melakukan sesuatu seperti

FIRST=$(( $6 + 1 ))
FIRST="${FIRST}q;d"
Giannis christofakis
sumber
1
Bisakah Anda menjelaskannya sedikit lebih baik. Tidak benar-benar mengerti apa yang Anda coba lakukan.
neuron
Apa yang harus dilakukan `$ name = $ (($ 6 + 1))`?
PSkocik
@PSkocik yang saya harapkanFIRST=$(( $6 + 1 ))
giannis christofakis

Jawaban:

16

Pertama-tama tidak ada ruang =di sekitar dalam deklarasi variabel dalam bash.

Untuk mendapatkan apa yang Anda inginkan, Anda dapat menggunakannya eval.

Misalnya skrip sampel seperti milik Anda:

#!/bin/bash
i=0
for name in FIRST SECOND THIRD FOURTH FIFTH; do
    eval "$name"="'$(( $i + 1 ))q;d'"
    printf '%s\n' "${!name}"
    i=$(( $i + 1 ))
done

Cetakan:

1q;d
2q;d
3q;d
4q;d
5q;d

Gunakan dengan evalhati-hati, beberapa orang menyebutnya jahat karena alasan yang masuk akal.

declare akan bekerja juga:

#!/bin/bash
i=0
for name in FIRST SECOND THIRD FOURTH FIFTH; do
    declare "$name"="$(( $i + 1 ))q;d"
    printf '%s\n' "${!name}"
    i=$(( $i + 1 ))
done

juga mencetak:

1q;d
2q;d
3q;d
4q;d
5q;d
heemayl
sumber
Untuk apa !tanda seru itu printf '%s\n' "${!name}"?
giannis christofakis
1
Ini disebut ekspansi tidak langsung dari ekspansi bashparameter..baca ini
heemayl
1
Bash juga memiliki alternatif lebih baik untuk declare/ eval: printf -v varname '%fmt' args. Beberapa fungsi internal penyelesaian-bash menggunakan ini untuk panggilan-oleh-referensi. (berikan nama variabel yang akan disimpan).
Peter Cordes
Catatan: Menggunakan declarehanya menetapkan variabel dalam lingkup lokal, sedangkan evalpendekatan menetapkannya secara global.
pengguna
11

Jika Anda ingin mereferensikan variabel bash sambil menyimpan nama di variabel lain, Anda dapat melakukannya sebagai berikut:

$ var1=hello
$ var2=var1
$ echo ${!var2}
hello

Anda menyimpan nama variabel yang ingin Anda akses, katakanlah, var2 dalam kasus ini. Maka Anda mengaksesnya dengan ${!<varable name>}mana <variable name>adalah variabel memegang nama variabel yang ingin Anda akses.

Eric Renouf
sumber
Ada cara portabel dengan eval var=\$$holdertetapi evalberbahaya!
gavenkoa
1
index=0;                                                                                                                                                                                                           
for name in FIRST SECOND THIRD FOURTH FIFTH; do
    name=$(($index + 1))
    echo "${name}q;d"
    index=$((index+1))
done

Itukah yang kamu coba?

neuron
sumber
1

Apa yang saya dapatkan dari kode Anda dan output yang Anda inginkan (koreksi saya jika saya salah):
Tidak ada penggunaan nama variabel "PERTAMA" / "KEDUA" / ..., Anda hanya perlu loop dengan indeks .. .

Ini akan melakukan pekerjaan:

for i in {1..5} ; do echo $i"q;d" ; done

csny
sumber
Ya, Anda benar, kecuali saya juga ingin melakukan fungsi aritmatika dengan variabel.
giannis christofakis
Bisakah Anda memberi contoh fungsi aritmatika ini? Apakah Anda memerlukan nama variabel (seperti "KETIGA") untuk itu atau hanya nilai indeks?
csny
SUM=$(($6 + $i)); echo $SUM"q;d", Saya melihat apa yang saya lakukan salah.
giannis christofakis