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"

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

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.


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?


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


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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.