GNU/Linux >> Linux Esercitazione >  >> Linux

Spiegazione del comando awk utilizzando ORS, NR, FS, RS

% è l'operatore modulo (vedi https://en.wikipedia.org/wiki/Modulo_operation) e NR%3?FS:RS è un'espressione ternaria (vedi https://en.wikipedia.org/wiki/%3F:). Questi sono entrambi costrutti comuni in molti linguaggi di programmazione, non sono specifici di awk. Per il significato di ORS, NR, FS e RS basta vedere la pagina man di awk.

Esegui questo per vedere i valori delle variabili nel codice prima e dopo il comando che stai eseguendo:

$ cat tst.awk
BEGIN {
    printf "%s=\"%s\"\n", "RS", RS
    printf "%s=\"%s\"\n", "FS", FS
}
{
    printf "---\n"

    printf "%s=\"%s\"\n", "$0", $0
    printf "%s=\"%s\"\n", "NR", NR
    printf "%s=\"%s\"\n", "NR%3", NR%3

    printf "before) %s=\"%s\"\n", "ORS", ORS

    ORS = (NR%3 ? FS : RS)

    printf "after) %s=\"%s\"\n", "ORS", ORS
}

.

$ awk -f tst.awk file
RS="
"
FS=" "
---
$0="1"
NR="1"
NR%3="1"
before) ORS="
"
after) ORS=" "
---
$0="2"
NR="2"
NR%3="2"
before) ORS=" "
after) ORS=" "
---
$0="3"
NR="3"
NR%3="0"
before) ORS=" "
after) ORS="
"
---
$0="4"
NR="4"
NR%3="1"
before) ORS="
"
after) ORS=" "
---
$0="5"
NR="5"
NR%3="2"
before) ORS=" "
after) ORS=" "
---
$0="6"
NR="6"
NR%3="0"
before) ORS=" "
after) ORS="
"

Nota su quali numeri di riga di input (NR ) il separatore di record di output (ORS ) diventa una nuova riga (come RS ) rispetto a un carattere vuoto (come FS ).

Un modo più prolisso per scrivere lo stesso codice sarebbe:

$ cat tst.awk
{
    if (NR%3 == 0) {
        ORS = "\n"
    }
    else {
        ORS = " "
    }

    print
}

$ awk -f tst.awk file
1 2 3
4 5 6

e Cordiali saluti, il modo corretto (più robusto e più chiaro) di scrivere il codice conciso e idiomatico tentato nella tua domanda sarebbe:

awk '{ORS=(NR%3?FS:RS)}1'

Le parentesi attorno al ternario sono richieste in alcuni awk in alcuni contesti e migliorano sempre la leggibilità, quindi usale sempre. Il codice originale si basa sul risultato dell'assegnazione a ORS che produce un valore diverso da null/diverso da zero in modo che sia una condizione vera e quindi richiama l'azione predefinita di awks per stampare il record corrente. Usa il risultato di un'azione in quel contesto solo quando ne hai BISOGNO altrimenti ti morderà un giorno quando i tuoi dati non saranno esattamente quelli che ti aspettavi. Invece di lasciare l'assegnazione in un blocco di condizione, l'ho spostata in un blocco di azione e successivamente ho aggiunto una condizione true costante, 1 per garantire che ogni record venga stampato indipendentemente dal risultato dell'assegnazione.


Non il awk spiegazione poiché hai già più di una buona risposta, ma alternative per lo stesso compito

$ seq 6 | xargs -n3
1 2 3
4 5 6

$ seq 6 | paste - - -
1       2       3
4       5       6

con paste il delimitatore predefinito è tab, che puoi cambiare in spazio con -d' '

$ seq 6 | pr -3ats' '
1 2 3
4 5 6

Linux
  1. Sostituzione dei comandi usando “?

  2. Esempi di utilizzo del comando dmsetup in Linux

  3. Esempi di comandi awk in Linux

  4. awk:comando non trovato

  5. Usando grep vs awk

Comando awk di Linux con 10 esempi

Una semplice spiegazione del comando NAMEI in Linux

Tutorial sull'uso del comando Timeout su Linux

Utilizzo del comando Watch in Linux

Comando AWK in Linux/Unix

Utilizzo di cut su terminale Linux