Como Usar a Linguagem AWK para Manipular Texto no Linux

Introdução

Os utilitários do Linux frequentemente seguem a filosofia de design do Unix. Incentiva-se que as ferramentas sejam pequenas, usem arquivos de texto simples para entrada e saída, e operem de forma modular. Devido a essa herança, temos uma ótima funcionalidade de processamento de texto com ferramentas como sed e awk.

awk é tanto uma linguagem de programação quanto um processador de texto que você pode usar para manipular dados de texto de maneiras muito úteis. Neste guia, você explorará como usar a ferramenta de linha de comando awk e como usá-la para processar texto.

Sintaxe Básica

O comando awk está incluído por padrão em todos os sistemas Linux modernos, então você não precisa instalá-lo para começar a usá-lo.

awk é mais útil ao lidar com arquivos de texto formatados de maneira previsível. Por exemplo, é excelente para analisar e manipular dados tabulares. Ele opera em uma base de linha por linha e itera por todo o arquivo.

Por padrão, ele usa espaços em branco (espaços, tabulações, etc.) para separar campos. Felizmente, muitos arquivos de configuração no seu sistema Linux usam esse formato.

O formato básico de um comando awk é:

  1. awk '/search_pattern/ { action_to_take_on_matches; another_action; }' file_to_parse

Você pode omitir a parte de busca ou a parte de ação de qualquer comando awk. Por padrão, a ação realizada se a parte “ação” não for fornecida é “print”. Isso simplesmente imprime todas as linhas que correspondem.

Se a parte de busca não for fornecida, o awk realiza a ação listada em cada linha.

Se ambos forem fornecidos, o awk usa a parte de busca para decidir se a linha atual reflete o padrão e, em seguida, executa as ações nas correspondências.

Em sua forma mais simples, você pode usar o awk como cat para imprimir todas as linhas de um arquivo de texto na tela.

Crie um arquivo favorite_food.txt que lista as comidas favoritas de um grupo de amigos:

  1. echo "carrot sandy
  2. wasabi luke
  3. sandwich brian
  4. salad ryan
  5. spaghetti jessica" > favorite_food.txt

Agora use o comando awk para imprimir o arquivo na tela:

  1. awk '{print}' favorite_food.txt

Você verá o arquivo impresso na tela:

Output
carrot sandy wasabi luke sandwich brian salad ryan spaghetti jessica

Isso não é muito útil. Vamos experimentar as capacidades de filtragem de pesquisa do awk pesquisando o arquivo pelo texto “sand”:

  1. awk '/sand/' favorite_food.txt
Output
carrot sandy sandwich brian

Como você pode ver, o awk agora imprime apenas as linhas que contêm os caracteres “sand”.

Usando expressões regulares, você pode segmentar partes específicas do texto. Para exibir apenas a linha que começa com as letras “sand”, use a expressão regular ^sand:

  1. awk '/^sand/' favorite_food.txt

Desta vez, apenas uma linha é exibida:

Output
sandwich brian

Da mesma forma, você pode usar a seção de ação para especificar quais informações deseja imprimir. Por exemplo, para imprimir apenas a primeira coluna, use o seguinte comando:

  1. awk '/^sand/ {print $1;}' favorite_food.txt
Output
sandwich

Você pode fazer referência a cada coluna (delimitada por espaços em branco) por meio de variáveis associadas ao número da coluna. Por exemplo, a primeira coluna é $1, a segunda é $2, e você pode referenciar a linha inteira com $0.

Variáveis Internas e Formato Expandido

O comando awk usa algumas variáveis internas para atribuir certas informações enquanto processa um arquivo.

As variáveis internas que o awk utiliza são:

  • FILENAME: Referencia o arquivo de entrada atual.
  • FNR: Referencia o número do registro atual em relação ao arquivo de entrada atual. Por exemplo, se você tiver dois arquivos de entrada, isso informaria o número do registro de cada arquivo, em vez do total.
  • FS: O separador de campo atual usado para denotar cada campo em um registro. Por padrão, isso é definido como espaço em branco.
  • NF: O número de campos no registro atual.
  • NR: O número do registro atual.
  • OFS: O separador de campo para os dados de saída. Por padrão, isso é definido como espaço em branco.
  • ORS: O separador de registro para os dados de saída. Por padrão, isso é um caractere de nova linha.
  • RS: O separador de registros usado para distinguir registros separados no arquivo de entrada. Por padrão, isso é um caractere de nova linha.

Você pode alterar os valores dessas variáveis conforme necessário para corresponder às necessidades de seus arquivos. Geralmente, você faz isso durante a fase de inicialização do seu processamento.

Isso nos leva a outro conceito importante. A sintaxe do awk é um pouco mais complexa do que a que você usou até agora. Existem também blocos opcionais BEGIN e END que podem conter comandos para executar antes e depois do processamento do arquivo, respectivamente.

Isso faz com que nossa sintaxe expandida se pareça com isso:

  1. awk 'BEGIN { action; }
  2. /search/ { action; }
  3. END { action; }' input_file

As palavras-chave BEGIN e END são conjuntos específicos de condições, assim como os parâmetros de pesquisa. Elas correspondem antes e depois do documento ter sido processado.

Isso significa que você pode alterar algumas das variáveis internas na seção BEGIN. Por exemplo, o arquivo /etc/passwd é delimitado por dois pontos (:) em vez de espaços em branco.

Para imprimir a primeira coluna deste arquivo, execute o seguinte comando:

  1. awk 'BEGIN { FS=":"; }
  2. { print $1; }' /etc/passwd
Output
root daemon bin sys sync games man . . .

Você pode usar os blocos BEGIN e END para imprimir informações sobre os campos que está imprimindo. Use o seguinte comando para transformar os dados do arquivo em uma tabela, bem espaçada com tabulações usando \t:

  1. awk 'BEGIN { FS=":"; print "User\t\tUID\t\tGID\t\tHome\t\tShell\n--------------"; }
  2. {print $1,"\t\t",$3,"\t\t",$4,"\t\t",$6,"\t\t",$7;}
  3. END { print "---------\nFile Complete" }' /etc/passwd

Você verá esta saída:

Output
User UID GID Home Shell -------------- root 0 0 /root /bin/bash daemon 1 1 /usr/sbin /bin/sh bin 2 2 /bin /bin/sh sys 3 3 /dev /bin/sh sync 4 65534 /bin /bin/sync . . . --------- File Complete

Como você pode ver, é possível formatar as coisas bastante bem aproveitando algumas das características do awk.

Cada uma das seções expandidas é opcional. Na verdade, a seção de ação principal em si também é opcional se outra seção for definida. Por exemplo, você pode fazer coisas como esta:

  1. awk 'BEGIN { print "We can use awk like the echo command"; }'

E você verá esta saída:

Output
We can use awk like the echo command

Agora vamos ver como procurar texto dentro dos campos da saída.

Pesquisa de Campo e Expressões Compostas

Em um dos exemplos anteriores, você imprimiu a linha no arquivo favorite_food.txt que começava com “sand”. Isso foi fácil porque você estava procurando pelo início da linha inteira.

E se você quisesse descobrir se um padrão de pesquisa corresponde ao início de um campo em vez disso?

Crie uma nova versão do arquivo favorite_food.txt que adiciona um número de item na frente da comida de cada pessoa:

  1. echo "1 carrot sandy
  2. 2 wasabi luke
  3. 3 sandwich brian
  4. 4 salad ryan
  5. 5 spaghetti jessica" > favorite_food.txt

Se você quiser encontrar todos os alimentos deste arquivo que começam com “sa”, você pode começar tentando algo assim:

  1. awk '/sa/' favorite_food.txt

Isso mostra todas as linhas que contêm “sa”:

Output
1 carrot sandy 2 wasabi luke 3 sandwich brian 4 salad ryan

Aqui, você está correspondendo a qualquer instância de “sa” na palavra. Isso acaba incluindo coisas como “wasabi”, que têm o padrão no meio, ou “sandy”, que não está na coluna que você deseja. Neste caso, você está interessado apenas em palavras que começam com “sa” na segunda coluna.

Você pode dizer ao awk para apenas fazer correspondência no início da segunda coluna usando este comando:

  1. awk '$2 ~ /^sa/' favorite_food.txt

Como você pode ver, isso nos permite procurar apenas no início da segunda coluna por uma correspondência.

A parte field_num ~ especifica que o awk deve prestar atenção apenas na segunda coluna.

Output
3 sandwich brian 4 salad ryan

Você também pode procurar facilmente por coisas que não correspondam incluindo o caractere “!” antes do til (~). Este comando retornará todas as linhas que não têm um alimento que comece com “sa”:

  1. awk '$2 !~ /^sa/' favorite_food.txt
Output
1 carrot sandy 2 wasabi luke 5 spaghetti jessica

Se você decidir mais tarde que está interessado apenas em linhas que não começam com “sa” e o número do item é menor que 5, você pode usar uma expressão composta como esta:

  1. awk '$2 !~ /^sa/ && $1 < 5' favorite_food.txt

Isso introduz alguns novos conceitos. O primeiro é a capacidade de adicionar requisitos adicionais para a linha corresponder usando o operador &&. Usando isso, você pode combinar um número arbitrário de condições para a linha corresponder. Neste caso, você está usando esse operador para adicionar uma verificação de que o valor da primeira coluna é menor que 5.

Você verá esta saída:

Output
1 carrot sandy 2 wasabi luke

Você pode usar o awk para processar arquivos, mas também pode trabalhar com a saída de outros programas.

Processando Saída de Outros Programas

Você pode usar o comando awk para analisar a saída de outros programas em vez de especificar um nome de arquivo. Por exemplo, você pode usar o awk para extrair o endereço IPv4 do comando ip.

O comando ip a exibe o endereço IP, endereço de broadcast e outras informações sobre todas as interfaces de rede em sua máquina. Para exibir as informações para a interface chamada eth0, use este comando:

  1. ip a s eth0

Você verá os seguintes resultados:

Output
2571: eth0@if2572: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:11:00:0b brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.17.0.11/16 brd 172.17.255.255 scope global eth0 valid_lft forever preferred_lft forever

Você pode usar o awk para direcionar a linha inet e então imprimir apenas o endereço IP:

  1. ip a s eth0 | awk -F '[\/ ]+' '/inet / {print $3}'

A bandeira -F informa ao awk para delimitar por barras diagonais ou espaços usando a expressão regular [\/ ]+. Isso divide a linha inet 172.17.0.11/16 em campos separados. O endereço IP está no terceiro campo porque os espaços no início da linha também contam como um campo, já que você delimitou por espaços e barras. Observe que o awk tratou espaços consecutivos como um único espaço neste caso.

A saída mostra o endereço IP:

Output
172.17.0.11

Você encontrará muitos lugares onde pode usar o awk para pesquisar ou analisar a saída de outros comandos.

Conclusão

Até agora, você deve ter uma compreensão básica de como pode usar o comando awk para manipular, formatar e imprimir seletivamente arquivos de texto e fluxos de texto. Awk é um tópico muito mais amplo, porém, e na verdade é uma linguagem de programação completa com atribuição de variáveis, estruturas de controle, funções integradas e muito mais. Você pode usá-lo dentro de seus próprios scripts para formatar texto de maneira confiável.

Para saber mais sobre awk, você pode ler o livro de domínio público gratuito de seus criadores que entra em muito mais detalhes.

Source:
https://www.digitalocean.com/community/tutorials/how-to-use-the-awk-language-to-manipulate-text-in-linux