Hacer referencia a elementos de matriz por cadenas e inicializar matrices en 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]
  }'

el comando anterior genera el último valor establecido para arr['subscript'], en este caso, 10es el valor de arr[Q]justo antes printy no 8el valor de arr[J].

Además, como en la secuencia de comandos anterior, no quiero asignar valores arr['A'], arr['B'], arr['C'] and arr['E']que tengan el mismo valor 1una línea a la vez, sino pasar una matriz de subíndices como uno de los parámetros y el valor común como el otro parámetro a una función que maneja La lógica de asignarles valor.

HarshvardhanSharma
fuente

Respuestas:

16

Los índices de matriz son enteros o cadenas entre comillas awk. Lo que está haciendo aquí es usar variables que aún no se han inicializado. Sus valores, por lo tanto, están vacíos.

Obtiene el último valor asignado a la matriz porque cada asignación sobrescribe el valor anterior. Usar print arr[""]también te 10devolvería.

En su lugar, use cadenas, como en arr["A"]=1.

Para su último problema: no hay una instalación real para inicializar una awkmatriz desde la línea de comando, pero puede pasar un valor "codificado" que "decodifica" en su BEGINbloque (por ejemplo) para extraer las claves y los valores de una matriz.

Ejemplo que pasa una lista especialmente delimitada como una sola cadena y la analiza para extraer los índices y valores a usar:

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

Usando claves y valores separados:

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

Esta es una forma bastante limitada de pasar una "matriz" awk, pero funciona para valores simples sobre los que uno tiene control total. Los ejemplos se romperían para cualquier dato que incorpore dos puntos (y signos iguales para el primer ejemplo) en los datos reales.

Pasar datos como este también significa que las barras invertidas en los datos deberán tratarse especialmente ( \nserá una nueva línea, por lo que para pasar la cadena de dos caracteres \n, debería usar "\\\n"o '\\n').

También relacionado:


Como comentario aparte, puede escribir un " awkguión puro " como este:

#!/usr/bin/awk -f

BEGIN { 
   # some initialisations
}

some_expression { some code }

END {
    # more here
}
Kusalananda
fuente