%
モジュロ演算子 (https://en.wikipedia.org/wiki/Modulo_operation を参照) および NR%3?FS:RS
は三項式です (https://en.wikipedia.org/wiki/%3F:を参照)。これらは両方とも多くのプログラミング言語で共通の構成要素であり、awk に固有のものではありません。 ORS、NR、FS、および RS の意味については、その awk のマニュアル ページを参照してください。
これを実行して、実行中のコマンドの前後のコード内の変数の値を確認します:
$ 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="
"
入力行番号 (NR
) 出力レコード区切り (ORS
) は改行になります (RS
のように) ) vs 空白文字 (FS
など) ).
同じコードをより詳細に記述する方法は次のとおりです:
$ cat tst.awk
{
if (NR%3 == 0) {
ORS = "\n"
}
else {
ORS = " "
}
print
}
$ awk -f tst.awk file
1 2 3
4 5 6
参考までに、あなたの質問で試みられた簡潔で慣用的なコードを書くための正しい(より堅牢で明確な)方法は次のとおりです。
awk '{ORS=(NR%3?FS:RS)}1'
一部のコンテキストでは一部の awks で三項を囲む括弧が必要であり、常に可読性が向上するため、常に使用してください。元のコードは、ORS への割り当ての結果に依存しており、null 以外の値またはゼロ以外の値を生成して、それが true 条件になるようにし、現在のレコードを出力する awks のデフォルト アクションを呼び出します。そのコンテキストでアクションの結果を使用する必要がある場合にのみ使用してください。そうしないと、ある日、データが期待どおりにならないときに噛まれます。割り当てを条件ブロックに残す代わりに、それをアクション ブロックに移動し、その後に一定の真の条件 1
を追加しました。 割り当ての結果に関係なく、すべてのレコードが確実に印刷されるようにします。
awk
ではありません すでに複数の適切な回答があるための説明ですが、同じタスクの代替案
$ seq 6 | xargs -n3
1 2 3
4 5 6
$ seq 6 | paste - - -
1 2 3
4 5 6
paste
で デフォルトの区切り文字はタブですが、-d' '
でスペースに変更できます
$ seq 6 | pr -3ats' '
1 2 3
4 5 6