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
é:
- 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:
- echo "carrot sandy
- wasabi luke
- sandwich brian
- salad ryan
- spaghetti jessica" > favorite_food.txt
Agora use o comando awk
para imprimir o arquivo na tela:
- awk '{print}' favorite_food.txt
Você verá o arquivo impresso na tela:
Outputcarrot 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:
- awk '/sand/' favorite_food.txt
Outputcarrot 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
:
- awk '/^sand/' favorite_food.txt
Desta vez, apenas uma linha é exibida:
Outputsandwich 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:
- awk '/^sand/ {print $1;}' favorite_food.txt
Outputsandwich
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:
- awk 'BEGIN { action; }
- /search/ { action; }
- 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:
- awk 'BEGIN { FS=":"; }
- { print $1; }' /etc/passwd
Outputroot
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
:
- awk 'BEGIN { FS=":"; print "User\t\tUID\t\tGID\t\tHome\t\tShell\n--------------"; }
- {print $1,"\t\t",$3,"\t\t",$4,"\t\t",$6,"\t\t",$7;}
- END { print "---------\nFile Complete" }' /etc/passwd
Você verá esta saída:
OutputUser 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:
- awk 'BEGIN { print "We can use awk like the echo command"; }'
E você verá esta saída:
OutputWe 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:
- echo "1 carrot sandy
- 2 wasabi luke
- 3 sandwich brian
- 4 salad ryan
- 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:
- awk '/sa/' favorite_food.txt
Isso mostra todas as linhas que contêm \sa:
Output1 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:
- 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.
Output3 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:
- awk '$2 !~ /^sa/' favorite_food.txt
Output1 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:
- 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:
Output1 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:
- ip a s eth0
Você verá os seguintes resultados:
Output2571: 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:
- 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:
Output172.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.