Referenciando elementos da matriz por cadeias e inicializando matrizes no 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]
  }'

o comando acima gera o último valor definido para arr['subscript'], nesse caso, 10o valor de um arr[Q]pouco antes printe não 8o valor de arr[J].

Além disso, como no script acima, não quero atribuir valores com arr['A'], arr['B'], arr['C'] and arr['E']o mesmo valor, 1uma linha de cada vez, mas transmitir uma matriz de subscritos como um dos parâmetros e valor comum como o outro parâmetro para uma função que lida com a lógica de atribuir valor a eles.

HarshvardhanSharma
fonte

Respostas:

16

Os índices de matriz são números inteiros ou seqüências de caracteres entre aspas awk. O que você está fazendo aqui está usando variáveis ​​que ainda não foram inicializadas. Seus valores são, portanto, vazios.

Você obtém o valor mais recente atribuído à matriz porque cada atribuição está substituindo o valor anterior. Usar print arr[""]também o 10devolveria.

Em vez disso, use cadeias, como em arr["A"]=1.

Para o seu último problema: Não existe um recurso real para inicializar uma awkmatriz a partir da linha de comando, mas você pode passar um valor "codificado" que você "decodifica" em seu BEGINbloco (por exemplo) para extrair as chaves e os valores de uma matriz.

Exemplo que passa uma lista especialmente delimitada como uma única sequência e a analisa para extrair os índices e valores a serem usados:

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

Essa é uma maneira bastante limitada de transmitir uma "matriz" awk, mas funciona para valores simples sobre os quais se tem controle total. Os exemplos seriam quebrados para qualquer dado que incorpore dois pontos (e sinais de igual para o 1º exemplo) nos dados reais.

Passar dados como esse também significa que as barras invertidas nos dados terão que ser tratadas especialmente ( \nserá uma nova linha; portanto, para passar a cadeia de dois caracteres \n, você precisará usar "\\\n"ou '\\n').

Também relacionado:


Como um aparte, você pode escrever um " awkscript puro " como este:

#!/usr/bin/awk -f

BEGIN { 
   # some initialisations
}

some_expression { some code }

END {
    # more here
}
Kusalananda
fonte