Referenzieren von Array-Elementen durch Zeichenfolgen und Initialisieren von Arrays in awk

8
#!/usr/bin/env bash
awk '
  BEGIN {
    arr[A]=1;
    arr[B]=1;
    arr[C]=1;
    arr[E]=1;
    arr[J]=8;
    arr[Q]=10;
    print arr[J]
  }'

Der obige Befehl gibt den zuletzt eingestellten Wert für aus arr['subscript']. In diesem Fall 10ist dies der Wert von arr[Q]kurz zuvor printund nicht 8der Wert von arr[J].

Wie im obigen Skript möchte ich auch nicht zeilenweise Werte mit arr['A'], arr['B'], arr['C'] and arr['E']demselben Wert zuweisen 1, sondern ein Array von Indizes als einen der Parameter und einen gemeinsamen Wert als anderen Parameter an eine Funktion übergeben, die diese Funktion verarbeitet die Logik, ihnen einen Wert zuzuweisen.

HarshvardhanSharma
quelle

Antworten:

16

Array-Indizes sind entweder Ganzzahlen oder Zeichenfolgen in Anführungszeichen awk. Sie verwenden hier Variablen, die noch nicht initialisiert wurden. Ihre Werte sind daher leer.

Sie erhalten den neuesten Wert, der dem Array zugewiesen wurde, da jede Zuweisung den vorherigen Wert überschreibt. Die Verwendung print arr[""]würde Ihnen auch etwas 10zurückgeben.

Verwenden Sie stattdessen Zeichenfolgen wie in arr["A"]=1.

Für Ihr letztes Problem: Es gibt keine echte Möglichkeit, ein awkArray über die Befehlszeile zu initialisieren. Sie können jedoch einen "codierten" Wert übergeben, den Sie BEGIN(beispielsweise) in Ihrem Block "decodieren" , um die Schlüssel und Werte für ein Array zu extrahieren.

Beispiel, bei dem eine speziell begrenzte Liste als einzelne Zeichenfolge übergeben und analysiert wird, um die zu verwendenden Indizes und Werte zu extrahieren:

awk -v vals="A=1:B=1:C=1:E=1:J=8:Q=10" '
    BEGIN {
        n = split(vals, v, ":")
        for (i = 1; i <= n; ++i) {
            split(v[i], a, "=")
            arr[a[1]] = a[2]
        }

        print arr["J"]
    }'

Verwenden separater Schlüssel und Werte:

awk -v keys="A:B:C:E:J:Q" -v vals="1:1:1:1:8:10" '
    BEGIN {
        nk = split(keys, k, ":")
        nv = split(vals, v, ":")

        if (nk != nv) exit 1

        for (i = 1; i <= nk; ++i)
            arr[k[i]] = v[i]

        print arr["J"]
    }'

Dies ist eine recht eingeschränkte Methode zum Übergeben eines "Arrays" awk, funktioniert jedoch für einfache Werte, über die man die vollständige Kontrolle hat. Die Beispiele würden für alle Daten unterbrochen, die Doppelpunkte (und Gleichheitszeichen für das erste Beispiel) in die tatsächlichen Daten einbetten.

Das Übergeben von Daten wie diesen bedeutet auch, dass Backslashes in den Daten speziell behandelt werden müssen ( \nes handelt sich um eine neue Zeile. Um die zwei Zeichenfolgen zu übergeben \n, müssten Sie "\\\n"oder verwenden '\\n').

Auch verwandt:


Nebenbei können Sie ein "reines awkSkript" wie folgt schreiben :

#!/usr/bin/awk -f

BEGIN { 
   # some initialisations
}

some_expression { some code }

END {
    # more here
}
Kusalananda
quelle