Référencement des éléments de tableau par des chaînes et initialisation des tableaux dans 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]
  }'

la commande ci-dessus génère la dernière valeur définie pour arr['subscript'], dans ce cas 10, il s'agit de la valeur arr[Q]juste avant printet non de 8la valeur de arr[J].

De plus, comme dans le script ci-dessus, je ne veux pas attribuer des valeurs à celles arr['A'], arr['B'], arr['C'] and arr['E']qui ont la même valeur 1une ligne à la fois, plutôt passer un tableau d'indices comme l'un des paramètres et une valeur commune comme l'autre paramètre à une fonction qui gère la logique de leur attribuer une valeur.

HarshvardhanSharma
la source

Réponses:

16

Les index de tableau sont des entiers ou des chaînes entre guillemets awk. Vous utilisez ici des variables qui n'ont pas encore été initialisées. Leurs valeurs sont donc vides.

Vous obtenez la dernière valeur affectée au tableau car chaque affectation remplace la valeur précédente. L'utilisation vous print arr[""]rendrait également 10.

Utilisez plutôt des chaînes, comme dans arr["A"]=1.

Pour votre dernier problème: il n'y a pas de véritable possibilité d'initialiser un awktableau à partir de la ligne de commande, mais vous pouvez passer une valeur "codée" que vous "décodez" dans votre BEGINbloc (par exemple) pour extraire les clés et les valeurs d'un tableau.

Exemple qui passe une liste spécialement délimitée comme une seule chaîne et l'analyse pour extraire les index et les valeurs à utiliser:

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"]
    }'

Utilisation de clés et de valeurs distinctes:

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"]
    }'

C'est une façon assez limitée de passer un "tableau" awk, mais cela fonctionne pour les valeurs simples sur lesquelles on a un contrôle complet. Les exemples se briseraient pour toutes les données qui incorporent des deux-points (et des signes égaux pour le 1er exemple) dans les données réelles.

La transmission de données comme celle-ci signifie également que les barres obliques inverses dans les données devront être traitées spécialement (ce \nsera une nouvelle ligne, donc pour passer la chaîne de deux caractères \n, vous devrez utiliser "\\\n"ou '\\n').

Également lié:


En passant, vous pouvez écrire un " awkscript pur " comme ceci:

#!/usr/bin/awk -f

BEGIN { 
   # some initialisations
}

some_expression { some code }

END {
    # more here
}
Kusalananda
la source