Aula 5 – Variáveis e Arrays

Aula 4 – Controlando a saída de dados | Índice | Aula 6 – Arrays multidimensionais


Seu apoio é muito importante para a criação e a manutenção dos cursos gratuitos do canal debxp:


Nesta aula…

  • Definindo variáveis na linha de comando
  • Como o AWK converte strings e números
  • Trabalhando com arrays
  • Percorrendo os valores de uma array
  • Utilizando números como índice
  • Lidando com variáveis indefinidas como índice
  • A instrução ‘delete’

Variáveis

  • Variáveis são uma forma de armazenar valores em um ponto do programa para utilizá-los depois em outras partes do programa.
  • O AWK permite a ciração de variáveis no corpo do programa e na linha de comando.
  • Nomes de variáveis podem conter sequências de letras do alfabeto inglês, números e o sublinhado.
  • Nomes de variáveis não podem começar com números.
  • Nomes de variáveis são sensíveis à caixa alta ou baixa.
  • O nome de uma variável é, por si só uma expressão que representa seu valor em determinado momento.
  • No AWK, as variáveis não precisam ser declaradas nem iniciadas.
  • Uma variável indefinida recebe por padrão o valor de uma string vazia.
  • As variáveis podem receber valores por operações de atribuição, incremento, decremento, ou através de funções.

Definindo variáveis na linha de comando

Qualquer variável para uso no programa em AWK pode ser definida na linha de comando (fora do programa) de duas formas:

  • Como parâmetro da opção -v;
  • Entre os arquivos de entrada de dados.

Criando variáveis com a opção ‘-v’

awk -v nome1=valor1 [-v nome2=valor2 ...] 'programa...' arquivos

Neste caso, as variáveis passam a existir antes do BEGIN. Por exemplo:

awk -v a=banana -v b=laranja 'BEGIN {print a, b}'
banana laranja

Criando variáveis entre os nomes de arquivos

awk 'programa...' var1=val1 var2=val2 arq1 var1=val3 arq2...

Aqui, as variáveis só existem durante a leitura dos arquivos.

Exemplo1:

:~$ lista=$'banana\nlaranja\nabacate'
:~$ awk '{ print a, $1 }' a=fruta <<< "$lista"
fruta banana
fruta laranja
fruta abacate

Exemplo2:

awk -F':' '
/gda/ {
    print a, $7
}

{
    if ($0 ~ a) print $0
}
' a=Shell /etc/passwd a=NAME /etc/os-release

Shell /bin/bash
PRETTY_NAME="Debian GNU/Linux 10 (buster)"
NAME="Debian GNU/Linux"
VERSION_CODENAME=buster

Como o AWK converte strings e números

O AWK converte strings em números, e vice-versa, de acordo com o contexto.

Exemplo:

:~$ awk 'BEGIN { a=3; b=4; print (a b) + 6 }'
40

Mas a conversão também pode ser forçada:

a = 10
b = a ""  <-- string
c = a + 0 <-- número

A variável interna CONVFMT determina o especificaor de formato para conversões de números para strings, e seu valor padrão é "%.6g".

Caso especial: se o número for um inteiro, ele sempre será convertido para uma string representando um valor inteiro, independente do valor em CONVFMT.

Exemplos:

# Conversão padrão...
:~$ awk 'BEGIN { a=10.2; b=a""; print b }'
10.2

# Aletrando CONVFMT...
:~$ awk 'BEGIN { CONVFMT="%.2f"; a=10.2; b=a""; print b }'
10.20

# Convertendo um inteiro...
:~$ awk 'BEGIN { CONVFMT="%.2f"; a=10; b=a""; print b }'
10

Trabalhando com arrays

Uma array é uma tabela de valores associados a índices.

Características:

  • O AWK permite o uso de arrays unidimensionais para armazenamento de strings e números relacionados entre si por um mesmo nome de variável.
  • Os nomes das arrays seguem as mesmas regras dos nomes de variáveis escalares.
  • Não pode haver nomes de variáveis iguais a nomes de arrays em um mesmo programa.
  • Não é preciso especificar o tamanho da array antes de utilizá-la.
  • Os índices podem ser números ou strings, mas sempre serão convertidos para strings.
  • No AWK as arrays são sempre associativas.
  • Os elementos de uma array são criados a partir da atribuição de um valor a um índice.

Percorrendo os valores em uma array

O AWK fornece a expressão ÍNDICE in ARRAY que tem duas finalidades de acordo com o contexto:

  • Verificar se ÍNDICE existe em ARRAY;
  • Percorrer cada ÍNDICE de ARRAY.

Exemplos:

1. Testando se o índice existe…

awk '
BEGIN {
    # Criando uma array de 5 elementos...
    for (n = 0; n < 5; n++) a[n]=n+1

    # Testando se o elemento '2' existe...
    if (2 in a)
        print "Existe!"
    else
        print "Não existe!"
}'

# Saída:
Existe!

2. Percorrendo os elementos da array…

awk '
BEGIN {
    # Criando uma array de 5 elementos...
    for (n = 0; n < 5; n++) a[n]=n+1

    # Percorrendo os elementos...
    for (i in a) print a[i]
}'

# Saída:
1
2
3
4
5

Por padrão, a ordem de iteração dos elementos de uma array é indefinida. O GAWK, porém, oferece uma série de chaves para ordenação na variável PROCINFO["sorted_in"]:

Valores:

"@unsorted"     - comportamento padrão.

"@ind_str_asc"  - ordem ascendente das strings.
"@ind_num_asc"  - ordem numérica ascendente.
"@val_type_asc" - ordem ascendente de valores (números primeiro).
"@val_str_asc"  - ordem ascendente de valores como strings.
"@val_num_asc"  - ordem ascendente de valores numéricos.

"@ind_str_desc"  - ordem descendente das strings.
"@ind_num_desc"  - ordem numérica descendente.
"@val_type_desc" - ordem descendente de valores (números primeiro).
"@val_str_desc"  - ordem descendente de valores como strings.
"@val_num_desc"  - ordem descendente de valores numéricos.

Utilizando números como índice

Como os índices são sempre strings, quando um valor numérico é utilizado ele é automaticamente convertido para uma string. Deste modo, o valor em CONVFMT pode levar a comportamentos inesperados. Por exemplo:

awk 'BEGIN {
    i = 12.345

    # Aqui, 'i' ainda é '12.345'...

    arr[i]="qualquer valor"
    CONVFMT = "%.2f"

    # Agora, 'i' será '12.34', porque a expressão
    # pressupõe uma string e faz a conversão...

    if (i in arr)
        print i, "existe!"
    else
        print i, "não existe!"
}'

# Saída:

12.345 não existe!

Lidando com variáveis indefinidas como índice

Outra consequência do fato dos índices serem sempre strings, é o fato de não haver conversão de tipo quando o índice for uma variável não definida, ou seja, seu valor será tratado como uma string vazia:

awk 'BEGIN {
    for (n = 0; n < 3; n++) {
        arr[i] = n
        print i, "=>", arr[i]
        i++
    }
}'

# Saída:

 => 0
1 => 1
2 => 2

Mas isso funciona…

lista=$'banana\nlaranja\nabacate'

awk '{
    arr[i++] = $0
}

END {
    for (n = 0; n < 3; n++) {
        print n, "=>", arr[n]
    }
}' <<< "$lista"

# Saída:

0 => banana
1 => laranja
2 => abacate

A instrução ‘delete’

Para remover um elemento da array:

delete array[índice]

Para remover toda uma array:

delete array

Importante! Mesmo depois de removida a array, seu nome continua registrado e não pode ser utilizado como nome de uma variável escalar!

awk 'BEGIN {
    arr[0] = "banana"
    delete arr
    arr = "laranja"
    print arr
}'

# Saída (erro!):

awk: fatal: tentativa de usar vetor "arr" em um contexto escalar

Aula 4 – Controlando a saída de dados | Índice | Aula 6 – Arrays multidimensionais

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Post comment