Pesquisa de site

Como usar a linguagem AWK para manipular texto no Linux


Introdução

Os utilitários do Linux geralmente seguem a filosofia de design do Unix. As ferramentas são encorajadas a serem pequenas, usar arquivos de texto simples para entrada e saída e operar de maneira modular. Devido a esse legado, temos uma excelente funcionalidade de processamento de texto com ferramentas como sed e awk.

awk é uma linguagem de programação e 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 é 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 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 os campos. Felizmente, muitos arquivos de configuração em 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 pesquisa ou a parte de ação de qualquer comando awk. Por padrão, a ação executada se a parte \action não for fornecida é \print. Isso simplesmente imprime todas as linhas correspondentes.

Se a parte de pesquisa não for fornecida, awk executará a ação listada em cada linha.

Se ambos forem fornecidos, awk usa a parte de pesquisa 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 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 os recursos de filtragem de pesquisa do awk procurando no arquivo pelo texto \sand:

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

Como você pode ver, awk agora só imprime as linhas que possuem os caracteres \sand nelas.

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ço em branco) por 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 à medida que processa um arquivo.

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

  • FILENAME: faz referência ao arquivo de entrada atual.
  • FNR: Refere-se ao número do registro atual relativo ao arquivo de entrada atual. Por exemplo, se você tiver dois arquivos de entrada, isso informará o número de 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, este é um caractere de nova linha.
  • RS: O separador de registro usado para distinguir registros separados no arquivo de entrada. Por padrão, este é um caractere de nova linha.

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

Isso nos leva a outro conceito importante. A sintaxe awk é um pouco mais complexa do que a que você usou até agora Existem também os 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 fique mais ou menos assim:

  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. Eles correspondem antes e depois do processamento do documento.

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 :

  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, você pode formatar as coisas muito bem aproveitando alguns dos recursos do awk.

Cada uma das seções expandidas é opcional. Na verdade, a própria seção de ação principal é opcional se outra seção for definida. Por exemplo, você pode fazer coisas assim:

  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 nos 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 o início de toda a linha.

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

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 tem o padrão no meio, ou \sandy, que não está na coluna desejada. Neste caso você esteja interessado apenas em palavras começando com \sa na coluna segunda.

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

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

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

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

Output
3 sandwich brian 4 salad ryan

Você pode pesquisar com a mesma facilidade por coisas que não correspondem incluindo o \!” caractere antes do til (~). Este comando retornará todas as linhas que não tiverem 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 só está interessado 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. A primeira é a capacidade de adicionar requisitos adicionais para a correspondência da linha usando o operador &&. Usando isso, você pode combinar um número arbitrário de condições para a linha corresponder. Nesse 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 awk para processar arquivos, mas também pode trabalhar com a saída de outros programas.

Processamento de 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 awk para analisar o endereço IPv4 do comando ip.

O comando ip a exibe o endereço IP, endereço de transmissão e outras informações sobre todas as interfaces de rede em sua máquina. Para exibir as informações da 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 awk para direcionar a linha inet e imprimir apenas o endereço IP:

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

O sinalizador -F diz ao awk para delimitar por barras 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, desde que você seja delimitado por espaços e barras. Observe que 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 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 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 em seus próprios scripts para formatar o 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 apresenta muito mais detalhes.