GNU/Linux >> Linux Esercitazione >  >> Linux

Migliora le tue abilità awk con due semplici tutorial

Awk è uno degli strumenti più vecchi nella cassetta degli attrezzi degli utenti Unix e Linux. Creato negli anni '70 da Alfred Aho, Peter Weinberger e Brian Kernighan (la A, W e K del nome dello strumento), awk è stato creato per l'elaborazione complessa di flussi di testo. È uno strumento complementare a sed, l'editor di flussi, progettato per l'elaborazione riga per riga di file di testo. Awk consente programmi strutturati più complessi ed è un linguaggio di programmazione completo.

Questo articolo spiegherà come utilizzare awk per attività più strutturate e complesse, inclusa una semplice applicazione di stampa unione.

Struttura del programma Awk

Uno script awk è costituito da blocchi funzionali circondati da {} (parentesi graffe). Esistono due blocchi funzione speciali, BEGIN e FINE , che vengono eseguiti prima dell'elaborazione della prima riga del flusso di input e dopo l'elaborazione dell'ultima riga. Nel mezzo, i blocchi hanno il formato:

pattern { action statements }

Ogni blocco viene eseguito quando la riga nel buffer di input corrisponde al modello. Se non è incluso alcun modello, il blocco funzione viene eseguito su ogni riga del flusso di input.

Inoltre, la seguente sintassi può essere utilizzata per definire funzioni in awk che possono essere richiamate da qualsiasi blocco:

function name(parameter list) { statements }

Questa combinazione di blocchi e funzioni di corrispondenza dei modelli consente allo sviluppatore di strutturare i programmi awk per il riutilizzo e la leggibilità.

Come awk elabora i flussi di testo

Awk legge il testo dal suo file di input o esegue lo streaming una riga alla volta e utilizza un separatore di campo per analizzarlo in un numero di campi. Nella terminologia awk, il buffer corrente è un record . Ci sono una serie di variabili speciali che influenzano il modo in cui awk legge ed elabora un file:

  • FS (separatore di campo):per impostazione predefinita, questo è qualsiasi spazio bianco (spazi o tabulazioni)
  • RS (separatore di record):per impostazione predefinita, una nuova riga (\n )
  • NF (numero di campi):quando awk analizza una riga, questa variabile viene impostata sul numero di campi che sono stati analizzati
  • $ 0: Il record corrente
  • $ 1, $ 2, $ 3, ecc.: Il primo, secondo, terzo campo, ecc. dal record corrente
  • NR (numero di record):il numero di record che sono stati analizzati finora dallo script awk

Ci sono molte altre variabili che influenzano il comportamento di awk, ma questo è sufficiente per cominciare.

Awk one-liners

Per uno strumento così potente, è interessante notare che la maggior parte dell'utilizzo di awk è costituito da battute di base. Forse il programma awk più comune stampa i campi selezionati da una riga di input da un file CSV, un file di registro, ecc. Ad esempio, il seguente one-liner stampa un elenco di nomi utente da /etc/passwd :

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

Come accennato in precedenza, $ 1 è il primo campo nel record corrente. Il -F opzione imposta la variabile FS sul carattere : .

Il separatore di campo può anche essere impostato in un blocco funzione BEGIN:

awk 'BEGIN { FS=":" } {print $1 }' /etc/passwd

Nell'esempio seguente, ogni utente la cui shell non è /sbin/nologin può essere stampato facendo precedere il blocco con un pattern match:

awk 'BEGIN { FS=":" } ! /\/sbin\/nologin/ {print $1 }' /etc/passwd

Awk avanzato:stampa unione

Ora che hai alcune nozioni di base, prova ad approfondire awk con un esempio più strutturato:creare una stampa unione.

Una stampa unione utilizza due file, uno (chiamato in questo esempio email_template.txt ) contenente un modello per un'email che desideri inviare:

From: Program committee <[email protected]>
To: {firstname} {lastname} <{email}>
Subject: Your presentation proposal

Dear {firstname},

Thank you for your presentation proposal:
  {title}

We are pleased to inform you that your proposal has been successful! We
will contact you shortly with further information about the event
schedule.

Thank you,
The Program Committee

E l'altro è un file CSV (chiamato proposals.csv ) con le persone a cui vuoi inviare l'email:

firstname,lastname,email,title
Harry,Potter,[email protected],"Defeating your nemesis in 3 easy steps"
Jack,Reacher,[email protected],"Hand-to-hand combat for beginners"
Mickey,Mouse,[email protected],"Surviving public speaking with a squeaky voice"
Santa,Claus,[email protected],"Efficient list-making"

Vuoi leggere il file CSV, sostituire i campi rilevanti nel primo file (saltando la prima riga), quindi scrivere il risultato in un file chiamato acceptanceN.txt , incrementando N per ogni riga che analizzi.

Scrivi il programma awk in un file chiamato mail_merge.awk . Le dichiarazioni sono separate da ; negli script awk. Il primo compito consiste nell'impostare la variabile del separatore di campo e un paio di altre variabili necessarie allo script. Devi anche leggere ed eliminare la prima riga nel CSV, altrimenti verrà creato un file che inizia con Gentile nome . Per farlo, usa la funzione speciale getline e azzerare il contatore dei record dopo averlo letto.

BEGIN {
  FS=",";
  template="email_template.txt";
  output="acceptance";
  getline;
  NR=0;
}

La funzione principale è molto semplice:per ogni riga elaborata viene impostata una variabile per i vari campi:nome , cognome , e-mail e titolo . Il file modello viene letto riga per riga e la funzione sub viene utilizzato per sostituire qualsiasi occorrenza delle sequenze di caratteri speciali con il valore della variabile pertinente. Quindi la riga, con le eventuali sostituzioni effettuate, viene inviata al file di output.

Poiché hai a che fare con il file modello e un file di output diverso per ogni riga, devi pulire e chiudere gli handle di file per questi file prima di elaborare il record successivo.

{
        # Read relevant fields from input file
        firstname=$1;
        lastname=$2;
        email=$3;
        title=$4;

        # Set output filename
        outfile=(output NR ".txt");

        # Read a line from template, replace special fields, and
        # print result to output file
        while ( (getline ln < template) > 0 )
        {
                sub(/{firstname}/,firstname,ln);
                sub(/{lastname}/,lastname,ln);
                sub(/{email}/,email,ln);
                sub(/{title}/,title,ln);
                print(ln) > outfile;
        }

        # Close template and output file in advance of next record
        close(outfile);
        close(template);
}

Hai finito! Esegui lo script sulla riga di comando con:

awk -f mail_merge.awk proposals.csv

o

awk -f mail_merge.awk < proposals.csv

e troverai i file di testo generati nella directory corrente.

Awk avanzato:conteggio della frequenza delle parole

Una delle funzionalità più potenti di awk è l'array associativo. Nella maggior parte dei linguaggi di programmazione, le voci di array sono in genere indicizzate da un numero, ma in awk, gli array sono referenziati da una stringa di chiave. Puoi memorizzare una voce dal file proposals.txt dalla sezione precedente. Ad esempio, in un singolo array associativo, come questo:

        proposer["firstname"]=$1;
        proposer["lastname"]=$2;
        proposer["email"]=$3;
        proposer["title"]=$4;

Ciò rende l'elaborazione del testo molto semplice. Un semplice programma che utilizza questo concetto è l'idea di un contatore di frequenza a parole. Puoi analizzare un file, suddividere le parole (ignorando la punteggiatura) in ogni riga, aumentare il contatore per ogni parola nella riga, quindi emettere le prime 20 parole che si trovano nel testo.

Innanzitutto, in un file chiamato wordcount.awk , imposta il separatore di campo su un'espressione regolare che includa spazi e segni di punteggiatura:

BEGIN {
        # ignore 1 or more consecutive occurrences of the characters
        # in the character group below
        FS="[ .,:;()<>{}@!\"'\t]+";
}

Successivamente, la funzione del ciclo principale eseguirà un'iterazione su ciascun campo, ignorando eventuali campi vuoti (cosa che accade se è presente la punteggiatura alla fine di una riga) e incrementerà il conteggio delle parole per le parole nella riga.

{
        for (i = 1; i <= NF; i++) {
                if ($i != "") {
                        words[$i]++;
                }
        }
}

Infine, dopo che il testo è stato elaborato, usa la funzione END per stampare il contenuto dell'array, quindi usa la capacità di awk di inserire l'output in un comando shell per eseguire un ordinamento numerico e stampare le 20 parole più frequenti:

END {
        sort_head = "sort -k2 -nr | head -n 20";
        for (word in words) {
                printf "%s\t%d\n", word, words[word] | sort_head;
        }
        close (sort_head);
}

L'esecuzione di questo script su una bozza precedente di questo articolo ha prodotto questo output:

[[email protected]]$ awk -f wordcount.awk < awk_article.txt 
the     79
awk     41
a       39
and     33
of      32
in      27
to      26
is      25
line    23
for     23
will    22
file    21
we      16
We      15
with    12
which   12
by      12
this    11
output  11
function        11

Cosa c'è dopo?

Più risorse Linux

  • Comandi Linux cheat sheet
  • Cheat sheet sui comandi avanzati di Linux
  • Corso online gratuito:Panoramica tecnica RHEL
  • Cheat sheet della rete Linux
  • Cheat sheet di SELinux
  • Cheat sheet dei comandi comuni di Linux
  • Cosa sono i container Linux?
  • I nostri ultimi articoli su Linux

Se vuoi saperne di più sulla programmazione di awk, ti ​​consiglio vivamente il libro Sed e awk di Dale Dougherty e Arnold Robbins.

Una delle chiavi per progredire nella programmazione awk è la padronanza delle "espressioni regolari estese". Awk offre diverse potenti aggiunte alla sintassi delle espressioni regolari sed con cui potresti già avere familiarità.

Un'altra grande risorsa per l'apprendimento di awk è la guida per l'utente di GNU awk. Ha un riferimento completo per la libreria di funzioni integrata di awk, oltre a molti esempi di script awk semplici e complessi.


Linux
  1. Scansiona la tua sicurezza Linux con Lynis

  2. Risolvi i problemi della tua rete con tcpdump

  3. Linux:come sincronizzare due cartelle con gli strumenti della riga di comando?

  4. Abbina due stringhe in una riga con grep

  5. Come sincronizzare due cartelle con gli strumenti della riga di comando?

Ravviva il tuo desktop Linux con Cinnamon

Comando AWK in Linux con esempi

Facile guida al monitoraggio dei tuoi sistemi con Checkmk

Metti alla prova le tue abilità BASH giocando a giochi da riga di comando

Gestisci l'interruzione di riga con i comandi Fold e FMT nel terminale Linux

10 tutorial Vim per far ripartire le tue abilità di editor