2016-09-29 12 views
0

Ich schreibe ein Bash-Skript, um einige Dateien zu analysieren. In einer ersten Iteration erstelle ich assoziative Arrays mit Wortzählungen für jede Kategorie, die analysiert wird. Diese Kategorien sind nicht im Voraus bekannt, daher sind die Namen dieser assoziativen Arrays variabel, aber alle mit demselben Präfix count_$category. Die assoziativen Arrays haben ein Wort als Schlüssel und ihr Vorkommen zählt in dieser Kategorie als Wert.Bash: Iterate über Variablennamen

Nachdem alle Dateien analysiert wurden, muss ich die Ergebnisse für jede Kategorie zusammenfassen. Ich kann mit ${count_*} über die Variablennamen iterieren, aber wie kann ich auf die assoziativen Arrays hinter diesen Variablennamen zugreifen? Für jedes assoziative Array (jede count_* Variable) sollte ich über die Wörter und ihre Zählungen iterieren.

Ich habe bereits mit indirekten Zugang wie dies versucht, aber es funktioniert nicht:

for categorycount in ${count_*} # categorycount now holds the name of the associative array variable for each category 
do 
    array=${!categorycount} 
    for word in ${!array[@]} 
    do 
     echo "$word occurred ${array[$word]} times" 
    done 
done 
+1

Können Sie ein [mcve] posten? Zum Beispiel: Bearbeiten Sie Ihren Code, um 2 assoziative Arrays zu füllen, und zeigen Sie uns, was Sie erwarten. –

+0

Gelöst: Ich habe endlich eine SO Frage gefunden, die dieses Problem beantwortet http://Stackoverflow.com/a/13306800/5324593 – OKamers

+0

Welche Version von bash? 4.3 hat eine neue Einrichtung direkt vor Ort. –

Antwort

2

Die moderne (bash 4.3+) Ansatz "namevars" verwendet, eine Anlage von KSH entlehnt:

for _count_var in "${[email protected]}"; do 
    declare -n count=$_count_var     # make count an alias for $_count_var 
    for key in "${!count[@]}"; do     # iterate over keys, via same 
     echo "$key occurred ${count[$key]} times" # extract value, likewise 
    done 
    unset -n count        # clear that alias 
done 

declare -n count=$count_var ermöglicht die Verwendung von "${count[foo]}" zur Suche nach Element foo im assoziativen Array count_var; In ähnlicher Weise wird count[foo]=bar demselben Element zugewiesen. unset -n count entfernt dann diese Zuordnung.


Prior 4.3 bash:

for _count_var in "${[email protected]}"; do 
    printf -v cmd '_count_keys=("${!%q[@]}")' "$_count_var" && eval "$cmd" 
    for key in "${_count_keys[@]}"; do 
    var="$_count_var[$key]" 
    echo "$key occurred ${!var} times" 
    done 
done 

Beachten Sie die Verwendung von %q, anstatt einen Variablennamen direkt in einen String ersetzen, um den Befehl zu eval zu erzeugen. Auch wenn wir in diesem Fall wahrscheinlich sicher sind (weil die Menge der möglichen Variablennamen eingeschränkt ist), verringert sich durch die Einhaltung dieser Vorgehensweise die Anzahl der Kontexte, die berücksichtigt werden müssen, um festzustellen, ob eine indirekte Erweiterung sicher ist.


In beiden Fällen beachten Sie, dass interne Variablen (_count_var, _count_keys usw.) Namen verwenden, der das count_* Muster nicht übereinstimmen.