%
je operátor modulo (viz https://en.wikipedia.org/wiki/Modulo_operation) a NR%3?FS:RS
je ternární výraz (viz https://en.wikipedia.org/wiki/%3F:). To jsou oba běžné konstrukce v mnoha programovacích jazycích, nejsou specifické pro awk. Pro význam ORS, NR, FS a RS se podívejte na manuálovou stránku awk.
Spusťte toto, abyste viděli hodnoty proměnných v kódu před a za příkazem, který provádíte:
$ 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="
"
Všimněte si, na kterých vstupních řádcích čísla (NR
) oddělovač výstupních záznamů (ORS
). ) se stane novým řádkem (jako RS
) oproti prázdnému znaku (např. FS
).
Podrobnější způsob, jak napsat stejný kód, by byl:
$ cat tst.awk
{
if (NR%3 == 0) {
ORS = "\n"
}
else {
ORS = " "
}
print
}
$ awk -f tst.awk file
1 2 3
4 5 6
a FYI správný (robustnější a jasnější) způsob, jak napsat stručný, idiomatický kód, o který jste se pokusili ve vaší otázce, by byl:
awk '{ORS=(NR%3?FS:RS)}1'
Závorky kolem trojky jsou v některých kontextech vyžadovány v některých awk a vždy zlepšují čitelnost, takže je vždy používejte. Původní kód se spoléhá na výsledek přiřazení k ORS, který vytváří nenulovou/nenulovou hodnotu, aby se jednalo o pravdivou podmínku, a tak vyvolá výchozí akci awks tisku aktuálního záznamu. Výsledek akce v tomto kontextu používejte pouze tehdy, když to POTŘEBUJETE, jinak vás jednoho dne kousne, když vaše data nebudou přesně taková, jak jste očekávali. Místo ponechání úkolu v bloku podmínky jsem ho přesunul do bloku akce a poté přidal konstantní pravdivou podmínku, 1
aby bylo zajištěno, že se každý záznam vytiskne bez ohledu na to, k čemu toto přiřazení vede.
Ne awk
vysvětlení, protože již máte více než jednu dobrou odpověď, ale alternativy pro stejný úkol
$ seq 6 | xargs -n3
1 2 3
4 5 6
$ seq 6 | paste - - -
1 2 3
4 5 6
s paste
výchozí oddělovač je tabulátor, který můžete změnit na mezeru pomocí -d' '
$ seq 6 | pr -3ats' '
1 2 3
4 5 6