Indirekte Variablenbewertung

7

Ich versuche, einen einfachen Wert für $ AR1_p1 zu drucken, aber die Variable $ i wird nicht ausgewertet.

for i in 1 2 3 4
do
AR1_p1=22
AR1_p2=23
AR1_p3=24
AR1_p3=25
echo $AR1_p$i
done 

Es ist wie eine dynamische Verkettung. Irgendwelche Vorschläge, wie man das behebt?.

serverliving.com
quelle
1
Vielleicht sollte die Echolinie lauten: echo $ AR1_p1 $ i
Parkamark
@parkamark, ich möchte, dass dies dynamisch ist wie p1, p2 usw.
serverliving.com
2
Sie sollten stattdessen Arrays verwenden. Was Sie wollen, ist nicht möglich (oder zumindest sehr schlechter Stil).
Sven
@Sven, ich verstehe, ich kann Arrays verwenden, aber da ich nur 4 Werte zu bewerten habe. Das ist also ein Problem mit Bash?
serverliving.com
@ serverliving.com nein, das ist kein Problem mit Bash. Bash verhält sich genau so, wie es sollte, und dies ist in der Tat ein Problem, für das es sinnvoll ist, ein Array zu verwenden. Warum ist es ein Problem, ein Array mit 4 Elementen zu verwenden?
Jules

Antworten:

6

Diese Schleife funktioniert. Andernfalls verwenden Sie Arrays.

$ for i in 1 2 3 4; do AR1_p1=22; AR1_p2=23; AR1_p3=24; AR1_p4=25; echo $((AR1_p$i)); done 
22
23
24
25
Joe
quelle
1
Beachten Sie, dass dies nur für ganzzahlige Parameter funktioniert.
Chepner
23

Sie können dafür indirekte Bash-Referenzen verwenden :

AR1_p1=22
AR1_p2=23
AR1_p3=24
AR1_p4=25
for i in 1 2 3 4
do
  VARNAME="AR1_p${i}"
  echo "${!VARNAME}"
done
zuazo
quelle
7

Gemäß den vorgeschlagenen Kommentaren sollte ein Array verwendet werden:

#!/bin/bash

AR1_p=(22 23 24 25)

for i in {1..4}
do
  echo "${AR1_p[$i-1]}"
done
Parkamark
quelle
Das macht keinen Sinn. Die forSchleife ist bereits eine Array-Zuordnung ...
mikeserv
Sie haben Recht, es macht keinen Sinn. Soweit dies Stimmen abgegeben hat, wurde die wahre Anforderung der ursprünglichen Frage nicht vollständig erfüllt. Dies wurde in der anderen Antwort oben in Bezug auf "indirekte Bash-Referenzen" angesprochen, die eine bessere Lösung für das darstellt, was das OP erreichen wollte. Mein Beitrag zeigt jedoch einige der Feinheiten, die in BASH eingesetzt werden können, um dasselbe zu erreichen, und stellt fest, dass das oben Gesagte einfach auf "für i in {22..25}; Echo $ i; erledigt" reduziert werden könnte. , aber diese Antwort hat keine wirkliche Relevanz für die ursprüngliche Frage.
Parkamark
3

Verwenden Sie eval:

#!/bin/bash

AR1_p1=22
AR1_p2=23
AR1_p3=24
AR1_p4=24
for i in 1 2 3 4
do
    eval echo \$AR1_p$i
done

Echo erweitert nur $ i. Wenn dieser Ausdruck eval erreicht, ist er wie folgt: $ AR1_p1. Eval versucht zu bewerten und gibt das Ergebnis.

Guru
quelle
6
evalist normalerweise eine schlechte Idee. In diesem Beispiel verarbeiten Sie natürlich keine externen Eingaben, aber wenn Sie dies jemals tun, müssen Sie sehr sicher sein, dass Sie alle Daten bereinigen, an die Sie übergeben eval. (Was schwer ist. Sehr schwer. Besser, es einfach zu überspringen.)
Wildcard
1
@ Wildcard - es ist wirklich nicht so schwer. Und zu lernen, wie man es richtig macht, sollte nicht übersprungen werden .
Mikeserv
1

POSIXly:

for i in 1 2 3 4
do  AR1_p1=22
    AR1_p2=23
    AR1_p3=24
    AR1_p4=25
    echo "$((AR1_p$i))"
done

Ein bisschen weniger chaotisch, vielleicht:

for i in 1 2 3 4
do  echo "$((AR1_p$i=i+21))"
done

Immer noch POSIX, aber weitaus vernünftiger:

i=0 n=21 l=4
while  [ "$l" -ge "$((i+=1))" ]
do     echo "$((AR1_p$i=i+n))"
done
mikeserv
quelle