GNU/Linux >> Tutoriels Linux >  >> Linux

Explication sur la commande awk utilisant ORS, NR, FS, RS

% est l'opérateur modulo (voir https://en.wikipedia.org/wiki/Modulo_operation) et NR%3?FS:RS est une expression ternaire (voir https://en.wikipedia.org/wiki/%3F:). Ce sont deux constructions courantes dans de nombreux langages de programmation, elles ne sont pas spécifiques à awk. Pour la signification de ORS, NR, FS et RS, consultez simplement cette page de manuel awk.

Exécutez ceci pour voir les valeurs des variables dans le code avant et après la commande que vous exécutez :

$ 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="
"

Remarquez sur quels numéros de ligne d'entrée (NR ) le séparateur d'enregistrements de sortie (ORS ) devient une nouvelle ligne (comme RS ) vs un caractère vide (comme FS ).

Une façon plus détaillée d'écrire le même code serait :

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

    print
}

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

et pour votre information, la manière correcte (plus robuste et plus claire) d'écrire le code concis et idiomatique tenté dans votre question serait :

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

Les parenthèses autour du ternaire sont nécessaires dans certains cas dans certains contextes et améliorent toujours la lisibilité, alors utilisez-les toujours. Le code d'origine s'appuie sur le résultat de l'affectation à ORS produisant une valeur non nulle/non nulle pour qu'il s'agisse d'une condition vraie et invoque ainsi l'action par défaut awks d'impression de l'enregistrement en cours. N'utilisez le résultat d'une action dans ce contexte que lorsque vous en avez BESOIN, sinon cela vous mordra un jour lorsque vos données ne correspondront pas exactement à ce que vous attendiez. Au lieu de laisser l'affectation dans un bloc de condition, je l'ai déplacée dans un bloc d'action, puis j'ai ajouté une condition vraie constante par la suite, 1 pour s'assurer que chaque enregistrement est imprimé, quel que soit le résultat de cette affectation.


Pas le awk explication puisque vous avez déjà plus d'une bonne réponse, mais des alternatives pour la même tâche

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

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

avec paste le délimiteur par défaut est la tabulation, que vous pouvez changer en espace avec -d' '

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

Linux
  1. Proxy TCP avec socat

  2. Substitution de commande à l'aide de " ?

  3. Utiliser –exclude avec la commande Du ?

  4. 10 exemples pratiques d'utilisation de la commande scp

  5. Utilisation de la commande ripgrep (rg) sous Linux

Commande Linux awk avec 10 exemples

Une explication simple de la commande NAMEI sous Linux

Tutoriel sur l'utilisation de la commande Timeout sous Linux

Utilisation de la commande Watch sous Linux

Commande AWK sous Linux/Unix

Utilisation de cut sur Linux Terminal