[erledigt] Bash: Array referenzieren

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
k2
Beiträge: 132
Registriert: 14.08.2002 22:29:28
Lizenz eigener Beiträge: MIT Lizenz

[erledigt] Bash: Array referenzieren

Beitrag von k2 » 17.04.2016 21:44:11

Hallo,

nachdem die Bash keine zweidimensionalen Arrays erlaubt, wollte ich als Workaround eindimensionale Arrays über ihren Namen referenzieren; leider klappt das nicht. Unten stehendes vereinfachtes Script sollte eigentlich das Array zahlen ausgeben - macht es aber nicht.

Code: Alles auswählen

#!/bin/bash
buchstaben=(a b c d e)
zahlen=(1 2 3 4 5)

array_auswahl='zahlen'

# nicht funktionierende Evaluierungen :-((
echo "ausgewähltes Array:  "${${!array_auswahl}[*]}

Gibt es da einen Fehler bei der Evaluierung des Arraynamens? Ich finde ihn nicht. Oder kann man nur "normale" Variablen referenzieren? Wäre ziemlich brrr - dann müsste ich ein zweidimensionales Array zusammenklopfen...

Vielen Dank für Eure Mühen
k2
Zuletzt geändert von k2 am 18.04.2016 19:09:34, insgesamt 1-mal geändert.

Benutzeravatar
heisenberg
Beiträge: 3546
Registriert: 04.06.2015 01:17:27
Lizenz eigener Beiträge: MIT Lizenz

Re: Bash: Array referenzieren

Beitrag von heisenberg » 17.04.2016 21:57:09

Hallo k2,

ich selbst bin ein fauler Sack und mach deswegen vieles in Bash. Doch
ein für mich wesentlicher Punkt ist, zu lernen, ab welcher grösse man
keine Bash mehr verwenden sollte. Bash ist keine Programmiersprache
und und ab einer gewissen Grösse wird das programmieren in Bash
sehr schmerzhaft und krampfig.

Der Punkt scheint mir mit zweidimensionalen Arrays erreicht zu sein.

Falls Du auf Schmerzen stehst, kannst Du aber gerne mit eval weiter
machen. Damit bekommst Du garantiert ein 2dimensionales Array ge-
griffen.

Grüße,
h.
Jede Rohheit hat ihren Ursprung in einer Schwäche.

k2
Beiträge: 132
Registriert: 14.08.2002 22:29:28
Lizenz eigener Beiträge: MIT Lizenz

Re: Bash: Array referenzieren

Beitrag von k2 » 17.04.2016 22:10:19

Vielen Dank für die schnelle Antwort - aber kann man Arrays jetzt referenzieren? Gibt es einen Fehler in der Syntax oder kann man nur normale Variablen referenzieren?

Benutzeravatar
heisenberg
Beiträge: 3546
Registriert: 04.06.2015 01:17:27
Lizenz eigener Beiträge: MIT Lizenz

Re: Bash: Array referenzieren

Beitrag von heisenberg » 17.04.2016 22:21:49

Beispiel eines assoziativen Arrays:

Code: Alles auswählen


# Wichtig! Die Variable muss als assoziatives Array deklariert werden, sonst sind nur numerische Indizies erlaubt
declare -A personen

# Beispieldaten zuweisen
personen[mueller_alter]=10

name=mueller
eigenschaft=alter
eval echo \$personen[${name}_${eigenschaft]
Nochmal als simples 2-dimensionales Array:

Code: Alles auswählen

declare -A matrix
matrix[0_9]=989
i=0
j=9
eval echo \${matrix[${i}_${j}]}
Jede Rohheit hat ihren Ursprung in einer Schwäche.

k2
Beiträge: 132
Registriert: 14.08.2002 22:29:28
Lizenz eigener Beiträge: MIT Lizenz

Re: Bash: Array referenzieren

Beitrag von k2 » 17.04.2016 22:44:41

Hi,
ich entnehme Deiner Antwort mal, dass man den Variablennamen eines eindimensionales Array nicht evaluieren kann so wie ich es vorhatte.
Ich werde dann wohl ein zweidimensionales Array nachbilden müssen ... jaaaa Schmerzen ...
Ein assoziatives Arrays nützt mir nichts, ich weiß an welcher Stelle was steht und kann das Array über einen numerischen Index bequem auslesen.

Aber ich muss Dir Recht geben:
Bash ist keine Programmiersprache und und ab einer gewissen Grösse wird das programmieren in Bash sehr schmerzhaft und krampfig.
mein Script ist derzeit bei 40k...

Vielen Dank für Deine Hilfe

uname
Beiträge: 12072
Registriert: 03.06.2008 09:33:02

Re: Bash: Array referenzieren

Beitrag von uname » 18.04.2016 08:19:55

Bash ist keine Programmiersprache und und ab einer gewissen Grösse wird das programmieren in Bash sehr schmerzhaft und krampfig.
mein Script ist derzeit bei 40k...
Ich habe mal in einen Ordner mit Perl-Scripten geschaut. Bei mehr als 100 Perl-Programmen liegt der Durchschnitt bei 5k bzw. bei weit unter 100 Zeilen.

Benutzeravatar
MegaV0lt
Beiträge: 163
Registriert: 21.11.2011 11:16:07
Lizenz eigener Beiträge: GNU General Public License
Kontaktdaten:

Re: Bash: Array referenzieren

Beitrag von MegaV0lt » 18.04.2016 08:28:44

Ein Beispiel aus meinem Backup-Skript

Code: Alles auswählen

      for pid in "${!JOBS[@]}" ; do
...
      done
Das Array JOBS wurde mit daclare -A Jobs definiert.
Dort gespeichert sind die PIDs von rsync-Processen und die dazugehörigen Profilnamen. Beispiel:
"echo ${JOBS[3295]}"
rsync_Prozess_1

Mit ${!JOBS[@]} werden die Namen der Indizes ausgegeben (3295, 3277, 3355, ...)

Schau Dir mal das hier an: http://wiki.bash-hackers.org/syntax/arrays
Oder: http://tldp.org/LDP/abs/html/arrays.html#ARRAYREF
"Das Internet? Gibt's diesen Blödsinn immer noch?"
[Homer Simpson], Sicherheitsinspektor im Kernkraftwerk Springfield.

k2
Beiträge: 132
Registriert: 14.08.2002 22:29:28
Lizenz eigener Beiträge: MIT Lizenz

Re: Bash: Array referenzieren

Beitrag von k2 » 18.04.2016 16:24:54

Danke für die Antwort, aber es scheint keine Möglichkeit zu geben, zwei indizierte Arrays über ihren _Namen_ zu referenzieren. Ich bastle einen Workaround...
Deine Links kenne ich, ich habe mich selbstverständlich ausführlich mit dem Problem der Referenzierung von Variablen und den Arrays auseinandergesetzt, bevor ich hier jemanden belästige (eval = "evil").

Gruß k2

Benutzeravatar
heisenberg
Beiträge: 3546
Registriert: 04.06.2015 01:17:27
Lizenz eigener Beiträge: MIT Lizenz

Re: [erledigt] Bash: Array referenzieren

Beitrag von heisenberg » 20.04.2016 20:56:37

So, heute habe ich auch mal so etwas 2-dimensionales gebraucht. So habe ich das umgesetzt:

Code: Alles auswählen

#!/bin/bash
#
#       Create CSV-Presentation Matrix of SQL-Data
#       for importing into a spreadsheet application
#
#       *** raw data from sql ***
#
#       permission_name_1;perm_value;user_name_1
#       permission_name_1;perm_value;user_name_2
#       permission_name_1;perm_value;user_name_3
#       ...
#       permission_name_2;perm_value;user_name_1
#       ...
#       permission_name_MAX;perm_value;user_name_MAX
#
#       *** output data ***
#
#       ;user_name_1;...;user_name_max
#       permission_name_1;perm_value_user_1;...;perm_value_user_MAX
#       ...
#       permission_name_MAX;perm_value_user_1;...;perm_value_user_MAX
#



SQL="
SELECT 
        permission.permission,
        (SELECT 1 FROM account2permission 
                WHERE           permission.id = account2permission.permissionid
                        AND     account.id = account2permission.accountid),
        account.comment 
FROM account, permission;"

    permission_name=""
permission_name_old=""
in_perm_record=0
   perm_record=1


while read line ; do

        IFS_OLD="$IFS"
        IFS=";"
        set $line
        IFS="$IFS_OLD"

        permission_name="$1"
        (( in_perm_record = $in_perm_record + 1 ))

        [ $in_perm_record -eq 1 ] && all_permission_names[$perm_record]=$permission_name

        eval $permission_name[$in_perm_record]="$2"

        if [ -n "$permission_name_old" -a "$permission_name" != "$permission_name_old" ]; then
                in_perm_record=0
                (( perm_record = $perm_record + 1 ))
        fi

        [ $perm_record -eq 1 ] && starface_users[$in_perm_record]="$3"
        permission_name_old="$permission_name"

done < <( echo "$SQL" | psql -t --no-align -F \; asterisk )

# Write header with usernames first
for u in "${starface_users[@]}";do 
        echo -n \;$u
done
echo 

for p in ${all_permission_names[@]};do
        echo -n $p
        for((user_index=0;$user_index < ${#starface_users[@]};user_index++));do
                eval echo -n "\;\${$p[$user_index]}"
        done
        echo 
done
Jede Rohheit hat ihren Ursprung in einer Schwäche.

Antworten