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.