Como usar o comando awk no Linux

Um laptop Linux com linhas de código em uma janela de terminal.
Fatmawati Achmad Zaenuri / Shutterstock

No Linux,  awké um dínamo de manipulação de texto de linha de comando, bem como uma linguagem de script poderosa. Aqui está uma introdução a alguns de seus recursos mais interessantes.

Como awk ganhou esse nome

awk comando foi nomeado usando as iniciais das três pessoas que escreveram a versão original em 1977:  Alfred Aho , Peter Weinberger e Brian Kernighan . Esses três homens eram do lendário  panteão Unix da AT&T Bell Laboratories . Com a contribuição de muitos outros desde então, awk continuou a evoluir.

É uma linguagem de script completa, bem como um kit de ferramentas completo de manipulação de texto para a linha de comando. Se este artigo aguça o apetite, você pode verificar todos os detalhes sobre  awk e sua funcionalidade.

Regras, padrões e ações

awktrabalha em programas que contêm regras compostas de padrões e ações. A ação é executada no texto que corresponde ao padrão. Os padrões são colocados entre chaves ( {}). Juntos, um padrão e uma ação formam uma regra. Todo o awkprograma está entre aspas simples ( ').

Vamos dar uma olhada no tipo de awkprograma mais simples . Não tem padrão, portanto, corresponde a cada linha de texto inserida nele. Isso significa que a ação é executada em todas as linhas. Vamos usá-lo na saída do whocomando.

Aqui está o resultado padrão de who:

Who

O comando "quem" em uma janela de terminal.

Talvez não precisemos de todas essas informações, mas, sim, queremos apenas ver os nomes nas contas. Podemos canalizar a saída whopara awke, em seguida, dizer awkpara imprimir apenas o primeiro campo.

Por padrão, awkconsidera um campo como uma string de caracteres cercada por espaços em branco, o início de uma linha ou o final de uma linha. Os campos são identificados por um cifrão ( $) e um número. Portanto,  $1representa o primeiro campo, que usaremos com a print ação para imprimir o primeiro campo.

Nós digitamos o seguinte:

quem | awk '{print $ 1}'

O comando "who | awk '{print $ 1}'" em uma janela de terminal.

awk imprime o primeiro campo e descarta o resto da linha.

Podemos imprimir quantos campos quisermos. Se adicionarmos uma vírgula como separador,  awkimprime um espaço entre cada campo.

Digitamos o seguinte para também imprimir a hora em que a pessoa se conectou (campo quatro):

quem | awk '{print $ 1, $ 4}'

O comando "who | awk '{print $ 1, $ 4}'" em uma janela de terminal.

Existem alguns identificadores de campo especiais. Eles representam toda a linha de texto e o último campo na linha de texto:

  • $ 0 : representa toda a linha de texto.
  • $ 1 : representa o primeiro campo.
  • $ 2 : representa o segundo campo.
  • $ 7 : representa o sétimo campo.
  • $ 45 : representa o 45º campo.
  • $ NF : Significa “número de campos” e representa o último campo.

Vamos digitar o seguinte para abrir um pequeno arquivo de texto que contém uma pequena citação atribuída a Dennis Ritchie :

gato dennis_ritchie.txt

O comando "cat dennis_ritchie.txt" em uma janela de terminal.

Queremos  awkimprimir o primeiro, o segundo e o último campo da cotação. Observe que, embora esteja enrolado na janela do terminal, é apenas uma única linha de texto.

Recomendado:  Como alternar o sombreamento de linha ou coluna no Planilhas Google

Nós digitamos o seguinte comando:

awk '{print $ 1, $ 2, $ NF}' dennis_ritchie.txt

O comando "awk '{print $ 1, $ 2, $ NF}' dennis_ritchie.txt" em uma janela de terminal.

Não conhecemos essa “simplicidade”. é o 18º campo na linha de texto, e não nos importamos. O que sabemos é que é o último campo e podemos usar $NFpara obter seu valor. O ponto final é considerado apenas mais um caractere do corpo do campo.

Adicionando Separadores de Campo de Saída

Você também pode informar awkpara imprimir um caractere específico entre os campos em vez do caractere de espaço padrão. A saída padrão do  date comando é um pouco peculiar  porque o tempo é colocado bem no meio dele. No entanto, podemos digitar o seguinte e usar awkpara extrair os campos que desejamos:

encontro
data | awk '{print $ 2, $ 3, $ 6}'

Os comandos "date" e "date | awk '{print $ 2, $ 3, $ 6}'" em uma janela de terminal.

Usaremos a OFS variável (separador de campo de saída) para colocar um separador entre o mês, dia e ano. Observe que a seguir colocamos o comando entre aspas simples ( '), não entre colchetes ( {}):

data | awk 'OFS = "/" {imprimir $ 2, $ 3, $ 6}'
data | awk 'OFS = "-" {imprimir $ 2, $ 3, $ 6}'

Os comandos "date | awk 'OFS =" / "{print $ 2, $ 3, $ 6}'" e "date | awk 'OFS =" - "{print $ 2, $ 3, $ 6}'" em uma janela de terminal.

As regras BEGIN e END

Uma BEGINregra é executada uma vez antes de iniciar qualquer processamento de texto. Na verdade, ele é executado antes awk mesmo de ler qualquer texto. Uma ENDregra é executada após a conclusão de todo o processamento. Você pode ter múltiplos BEGIN e  ENDregras, e eles vão executar em ordem.

Para nosso exemplo de BEGINregra, imprimiremos a citação inteira do dennis_ritchie.txtarquivo que usamos anteriormente com um título acima dela.

Para fazer isso, digitamos este comando:

awk 'BEGIN {print "Dennis Ritchie"} {print $ 0}' dennis_ritchie.txt

O comando "awk 'BEGIN {print" Dennis Ritchie "} {print $ 0}' dennis_ritchie.txt" em uma janela de terminal.

Observe que a BEGINregra tem seu próprio conjunto de ações dentro de seu próprio conjunto de chaves ( {}).

Podemos usar essa mesma técnica com o comando que usamos anteriormente para canalizar a saída de whopara awk. Para fazer isso, digitamos o seguinte:

quem | awk 'BEGIN {print "Sessões Ativas"} {print $ 1, $ 4}'

O comando "who | awk 'BEGIN {print" Active Sessions "} {print $ 1, $ 4}'" em uma janela de terminal.

Separadores de campo de entrada

Se você deseja awktrabalhar com texto que não usa espaços em branco para separar campos, você deve informar qual caractere o texto usa como separador de campo. Por exemplo, o /etc/passwdarquivo usa dois pontos ( :) para separar os campos.

Usaremos esse arquivo e a opção -F(string separadora) para dizer awkpara usar dois pontos ( :) como separador. Nós digitamos o seguinte para informar awk a impressão do nome da conta do usuário e da pasta pessoal:

awk -F: '{print $ 1, $ 6}' / etc / passwd

O comando "awk -F: '{print $ 1, $ 6}' / etc / passwd" em uma janela de terminal.

A saída contém o nome da conta do usuário (ou nome do aplicativo ou daemon) e a pasta pessoal (ou a localização do aplicativo).

Recomendado:  Como desativar (ou limpar) o recurso de preenchimento automático no Outlook

Saída do comando "awk -F: '{print $ 1, $ 6}' / etc / passwd" em uma janela de terminal.

Adicionando Padrões

Se tudo o que nos interessa são contas de usuário regulares, podemos incluir um padrão com nossa ação de impressão para filtrar todas as outras entradas. Como os  números de ID do usuário são iguais ou maiores que 1.000, podemos basear nosso filtro nessas informações.

Digitamos o seguinte para executar nossa ação de impressão apenas quando o terceiro campo ( $3) contém um valor igual ou superior a 1.000:

awk -F: '$ 3> = 1000 {print $ 1, $ 6}' / etc / passwd

O comando "awk -F: '$ 3> = 1000 {print $ 1, $ 6}' / etc / passwd" em uma janela de terminal.

O padrão deve preceder imediatamente a ação com a qual está associado.

Podemos usar a BEGINregra para fornecer um título para nosso pequeno relatório. Digitamos o seguinte, usando a \nnotação ( ) para inserir um caractere de nova linha na string de título:

awk -F: 'BEGIN {print "Contas de usuário \ n -------------"} $ 3> = 1000 {print $ 1, $ 6}' / etc / passwd

O comando "awk -F: 'BEGIN {print" Contas de usuário \ n ------------- "} $ 3> = 1000 {print $ 1, $ 6}' / etc / passwd" em um terminal janela.

Os padrões são expressões regulares completas e são uma das glórias de awk.

Digamos que desejamos ver os identificadores exclusivos universalmente (UUIDs) dos sistemas de arquivos montados. Se pesquisarmos no /etc/fstabarquivo por ocorrências da string “UUID”, ele deve retornar essa informação para nós.

Usamos o padrão de pesquisa “/ UUID /” em nosso comando:

awk '/ UUID / {print $ 0}' / etc / fstab

O comando "awk '/ UUID / {print $ 0}' / etc / fstab" em uma janela de terminal.

Ele encontra todas as ocorrências de “UUID” e imprime essas linhas. Na verdade, teríamos obtido o mesmo resultado sem a printação, porque a ação padrão imprime toda a linha de texto. Para maior clareza, porém, geralmente é útil ser explícito. Ao examinar um script ou arquivo de histórico, você ficará feliz por ter deixado pistas para si mesmo.

A primeira linha encontrada foi uma linha de comentário e, embora a string “UUID” esteja no meio dela, awkainda assim a encontrei. Podemos ajustar a expressão regular e dizer awkpara processar apenas linhas que começam com “UUID”. Para fazer isso, digitamos o seguinte, que inclui o token de início de linha ( ^):

awk '/ ^ UUID / {print $ 0}' / etc / fstab

O comando "awk '/ ^ UUID / {print $ 0}' / etc / fstab" em uma janela de terminal.

Isso é melhor! Agora, vemos apenas instruções de montagem genuínas. Para refinar ainda mais a saída, digitamos o seguinte e restringimos a exibição ao primeiro campo:

awk '/ ^ UUID / {print $ 1}' / etc / fstab

O comando "awk '/ ^ UUID / {print $ 1}' / etc / fstab" em uma janela de terminal.

Se tivéssemos vários sistemas de arquivos montados nesta máquina, obteríamos uma tabela organizada de seus UUIDs.

Funções integradas

awktem muitas funções que você pode chamar e usar em seus próprios programas , tanto na linha de comando quanto em scripts. Se você cavar um pouco, verá que é muito frutífero.

Para demonstrar a técnica geral para chamar uma função, veremos algumas numéricas. Por exemplo, o seguinte imprime a raiz quadrada de 625:

awk 'BEGIN {print sqrt (625)}'

Este comando imprime o arco tangente de 0 (zero) e -1 (que passa a ser a constante matemática, pi):

awk 'BEGIN {print atan2 (0, -1)}'

No comando a seguir, modificamos o resultado da atan2()função antes de imprimi-lo:

awk 'BEGIN {print atan2 (0, -1) * 100}'

As funções podem aceitar expressões como parâmetros. Por exemplo, esta é uma maneira complicada de pedir a raiz quadrada de 25:

awk 'BEGIN {print sqrt ((2 + 3) * 5)}'

O comando "awk 'BEGIN {print sqrt (625)}'" em uma janela de terminal.

scripts awk

Se sua linha de comando ficar complicada ou se você desenvolver uma rotina que sabe que deseja usar novamente, pode transferir seu awkcomando para um script.

Recomendado:  Como ver quais informações privadas seus aplicativos do iPhone estão acessando

Em nosso script de exemplo, vamos fazer tudo a seguir:

  • Diga ao shell qual executável usar para executar o script.
  • Prepare-se awkpara usar a FSvariável separadora de campo para ler o texto de entrada com campos separados por dois pontos ( :).
  • Use o OFSseparador de campo de saída para informar awka usar dois pontos ( :) para separar campos na saída.
  • Defina um contador para 0 (zero).
  • Defina o segundo campo de cada linha de texto com um valor em branco (é sempre um “x”, portanto, não precisamos vê-lo).
  • Imprima a linha com o segundo campo modificado.
  • Aumente o contador.
  • Imprima o valor do contador.

Nosso script é mostrado abaixo.

Exemplo de um script awk em um editor.

A BEGINregra realiza as etapas preparatórias, enquanto a  ENDregra exibe o valor do contador. A regra do meio (que não tem nome, nem padrão para corresponder a todas as linhas) modifica o segundo campo, imprime a linha e incrementa o contador.

A primeira linha do script informa ao shell qual executável usar ( awkem nosso exemplo) para executar o script. Também passa a -fopção (nome do arquivo) para awk, que informa que o texto a ser processado virá de um arquivo. Vamos passar o nome do arquivo para o script quando o executarmos.

Incluímos o script abaixo como texto para que você possa recortar e colar:

#! / usr / bin / awk -f

INÍCIO {
  # definir os separadores de campo de entrada e saída
  FS = ":"
  OFS = ":"
  # zere o contador de contas
  contas = 0
}
{
  # definir o campo 2 para nada
  $ 2 = ""
  # imprime a linha inteira
  imprimir $ 0
  # conta outra conta
  contas ++
}
FIM {
  # imprime os resultados
  imprimir contas "contas. \ n"
}

Salve isso em um arquivo chamado omit.awk. Para fazer o script executabl e , nós digite o seguinte usando chmod:

chmod + x omit.awk

O comando "chmod + x omit.awk" em uma janela de terminal.

Agora, vamos executá-lo e passar o /etc/passwdarquivo para o script. Este é o arquivo que  awkserá processado para nós, usando as regras do script:

./omit.awk / etc / passwd

O comando "./omit.awk / etc / passwd" em uma janela de terminal.

O arquivo é processado e cada linha é exibida, conforme mostrado abaixo.

Saída de "./omit.awk / etc / passwd" em uma janela de terminal.

As entradas “x” no segundo campo foram removidas, mas observe que os separadores de campo ainda estão presentes. As linhas são contadas e o total é dado na parte inferior da saída.

awk não significa estranho

awknão significa estranho; significa elegância. Ele foi descrito como um filtro de processamento e um redator de relatórios. Mais precisamente, é ambos, ou melhor, uma ferramenta que você pode usar para ambas as tarefas. Em apenas algumas linhas,  awk atinge o que requer uma codificação extensa em uma linguagem tradicional.

Esse poder é aproveitado pelo conceito simples de regras que contêm padrões, que selecionam o texto a processar e ações que definem o processamento.