2016-07-24 4 views
3

Ich habe ein ArrayDynamisch Name Array mit variabler während der Iteration über ein anderes Array in BASH

FIRST_ARRAY=(NEWYORK CALIFORNIA TEXAS) 

Ein Skript, das ein Staat Städte akzeptiert in diesem Zustand

Zum Beispiel die folgende zurückkehren würde zurückkehren können:

[email protected]:~$ search NEWYORK cities 
newyorkcity 
buffalo 
albany 

[email protected]:~$ search CALIFORNIA cities 
sanfrancisco 
paloalto 
losangeles 

[email protected]:~$ search TEXAS cities 
houston 
dallas 
austin 

Ich mag würde iterieren FIRST_ARRAY

for state in ${FIRST_ARRAY[@]} 
    do 
    cities=`search ${FIRST_ARRAY[state]} cities` 
    ARRAY_$state=($cities} 
done 

Am Ende würde ich die folgenden Arrays erwarten erstellt wurden, und sie würden die folgenden Werte

ARRAY_NEWYORK=(newyorkcity buffalo albany) 
ARRAY_CALIFORNIA=(sanfrancisco paloalto losangeles) 
ARRAY_TEXAS=(houston dallas austin) 

Wenn das funktioniert, dann zum Beispiel enthalten, würde ich austin zugreifen zu können, wie von

meint den dynamisch erstellte Array in der folgenden Art und Weise Aufruf
echo ${ARRAY_TEXAS[2]} 

Dank!

+0

http://stackoverflow.com/questions/16553089/bash- dynamic-variable-name – sozkul

+0

Es wird nicht versucht, eine Variable dynamisch zu benennen. Versuch, ein Array während der Schleifenlaufzeit dynamisch zu benennen. – ARL

+0

auch http://unix.stackexchange.com/questions/288886/bash-array-values-like-variables-inside-loop – Sundeep

Antwort

3

Auf Bash 4.0 oder höher, mit readarray/mapfile verfügbar, dient die folgende als lapidare und korrekte Umsetzung:

for state in "${FIRST_ARRAY[@]}"; do 
    readarray -t "ARRAY_$state" < <(search "$state" cities) 
done 

In bash 4.3, eine sichere, wörtliche Übersetzung des Codes steht zur Verfügung:

for state in "${FIRST_ARRAY[@]}"; do 
    readarray -t cities < <(search "$state" cities) 

    # make "dest" a namevar -- an alias -- for your intended destination 
    # skip to next state if current state name is invalid 
    # otherwise we could be assigning to an utterly different "dest" 
    declare -n dest="ARRAY_$state" || continue 

    # assign to that namevar 
    dest=("$cities") 

    # and discard it 
    unset -n dest 
done 

In bash 3.x erfordert dies sicher tun einige printf %q Magie Inhalt herzustellen, indem man eval analysiert werden:

for state in "${FIRST_ARRAY[@]}"; do 

    # why this, and not array=($cities)? Try a city with spaces in its name. 
    # or look at what happens when you have a "city name" that's a wildcard. 
    cities=() 
    while read -r city; do 
     cities+=("$city") 
    done < <(search "$state" cities) 

    # generate eval-safe replacement for the cities array 
    printf -v cities_str '%q ' "${cities[@]}" 

    # extra paranoia: make sure we fail with a parse error rather than doing something 
    # unexpected if the state name is not a valid shell variable 
    printf -v eval_str 'ARRAY_%q=(%s)' "$state" "$cities_str" 

    eval "$eval_str" # and evaluate that 
done 

Die ursprüngliche Frage prüfbar Antworten nicht eine Implementierung von search schaffen zu machen. Für diese Antwort bin ich mit den folgenden:

search() { 
    case $1 in 
    NEWYORK) printf '%s\n' newyorkcity buffalo albany ;; 
    CALIFORNIA) printf '%s\n' sanfrancisco paloalto losangeles ;; 
    TEXAS) printf '%s\n' houston dallas austin ;; 
    esac 
} 

Mit dem oben definiert sind, können die Ergebnisse überprüft werden, wie folgt:

$ declare -p ARRAY_NEWYORK ARRAY_CALIFORNIA ARRAY_TEXAS 
declare -a ARRAY_NEWYORK='([0]="newyorkcity" [1]="buffalo" [2]="albany")' 
declare -a ARRAY_CALIFORNIA='([0]="sanfrancisco" [1]="paloalto" [2]="losangeles")' 
declare -a ARRAY_TEXAS='([0]="houston" [1]="dallas" [2]="austin")' 
+0

Charles, ich hätte darauf hinweisen sollen, dass ich BASH 4 benutze.1, das hätte dir eine Menge Ärger ersparen können. Ich entschuldige mich im Voraus (obwohl es praktisch ist, zu wissen, wie man diese Lösung auch in älteren Situationen anwendet). 'search' ist ein Inhouse-cli, der mongodb abfragt. Gibt es noch andere Informationen, die ich zur Verfügung stellen könnte, um mehr zu helfen? – ARL

+0

Ihre erste Lösung war genau richtig und gab mir genau das Ergebnis, auf das ich gehofft hatte. Jetzt, da ich weiß, dass das invertierte Array die Lösung ist, kann ich etwas nachlesen und besser verstehen, wie es funktioniert. Vielen Dank für Ihre Zeit und Mühe in solch einer informativen Antwort! – ARL

+0

Ich entschuldige mich - die Erwähnung der "umgekehrten Anordnung" im ersten Absatz war tatsächlich Teil einer Abänderung, die mir schließlich bewusst wurde, dass sie unnötig war und entfernt wurde. (Dies hätte eine Alternative zu '$ {FIRST_ARRAY [state]}' geliefert, die tatsächlich dem Index zugeordnet wurde, aber beim genaueren Hinsehen erkannte ich, dass diese Erweiterung einfach durch '$ state' ersetzt werden konnte. –