%
es el operador de módulo (ver https://en.wikipedia.org/wiki/Modulo_operation) y NR%3?FS:RS
es una expresión ternaria (ver https://en.wikipedia.org/wiki/%3F:). Ambas son construcciones comunes en muchos lenguajes de programación, no son específicas de awk. Para conocer el significado de ORS, NR, FS y RS, consulte la página de manual de awk.
Ejecute esto para ver los valores de las variables en el código antes y después del comando que está ejecutando:
$ 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="
"
Observe en qué números de línea de entrada (NR
) el Separador de registros de salida (ORS
) se convierte en una nueva línea (como RS
) frente a un carácter en blanco (como FS
).
Una forma más detallada de escribir el mismo código sería:
$ cat tst.awk
{
if (NR%3 == 0) {
ORS = "\n"
}
else {
ORS = " "
}
print
}
$ awk -f tst.awk file
1 2 3
4 5 6
y FYI, la forma correcta (más robusta y más clara) de escribir el código idiomático conciso intentado en su pregunta sería:
awk '{ORS=(NR%3?FS:RS)}1'
Los paréntesis alrededor del ternario se requieren en algunos awks en algunos contextos y siempre mejoran la legibilidad, así que utilícelos siempre. El código original se basa en el resultado de la asignación a ORS que produce un valor no nulo/distinto de cero para que sea una condición verdadera y así invocar la acción predeterminada de awks de imprimir el registro actual. Solo use el resultado de una acción en ese contexto cuando NECESITE hacerlo; de lo contrario, lo morderá un día cuando sus datos no sean exactamente lo que esperaba. En lugar de dejar la asignación en un bloque de condición, la moví a un bloque de acción y luego agregué una condición verdadera constante, 1
para garantizar que todos los registros se impriman independientemente de los resultados de la asignación.
No el awk
explicación ya que ya tienes más de una buena respuesta, pero alternativas para la misma tarea
$ seq 6 | xargs -n3
1 2 3
4 5 6
$ seq 6 | paste - - -
1 2 3
4 5 6
con paste
el delimitador predeterminado es la pestaña, que puede cambiar a espacio con -d' '
$ seq 6 | pr -3ats' '
1 2 3
4 5 6