Entiendo cómo usar la función printf de awk, pero no quiero especificar cada campo.
Por ejemplo, suponga que este es mi archivo:
c1|c2|c3|c4|c5
c6|c7|c8|c9|c10
c11|c12|c13|c14|c15
Quiero formatearlo para que el primer campo de cada registro tenga el ancho de c11, la celda más larga en el primer campo:
c1 |c2|c3|c4|c5
c6 |c7|c8|c9|c10
c11|c12|c13|c14|c15
Entiendo que podría especificar:
awk -F"|" '{printf "%-3s%s%s%s%s\n", $1, $2, $3, $4, $5}' file > newfile
Supongamos que sé cuál quiero que sea el ancho de la primera columna, pero NO sé cuántos campos hay en el archivo. Básicamente quiero hacer algo como:
... '{printf "%-3s|", $1}'
... y luego imprima el resto de los campos en su formato original.
awk
text-formatting
printf
Kayli O'Keefe
fuente
fuente
sed 's/|/'' '' '' |/;s/\(...\) */\1/'
(aquí agregando citas adicionales para insertar esos 3 espacios a medida que los comentarios de SE exprimen espacios contiguos en uno)Respuestas:
Puede usar solo
sprintf
para volver a formatear$1
.Ex.
fuente
awk -vf1=3 'BEGIN{OFS=FS="|"}{$1=sprintf("%-*s",f1,$1)}1' test.txt
Para calcular la longitud más grande / más larga del primer campo, y luego formatear los valores en el campo de acuerdo con esa longitud, tendrá que hacer dos pases separados sobre el archivo.
(tenga en cuenta que el archivo de entrada se especifica dos veces en la línea de comando)
Para los datos que presenta, esto produciría
La primera pasada es manejada por el
FNR == NR
bloque, que simplemente realiza un seguimiento del campo más largo visto hasta ahora (m
contiene la longitud máxima vista) y salta a la siguiente línea.La segunda pasada es manejada por el último bloque, que formatea el primer campo usando
sprintf()
. La cadena de formato%-*s
significa "una cadena justificada a la izquierda cuyo ancho viene dado por el argumento entero antes del argumento que contiene la cadena real".Obviamente, esto podría expandirse para hacer todas las columnas al convertir el escalar
m
en una matriz que contenga el ancho máximo de cada columna:fuente
La forma inteligente es lo que sugirió Steeldriver . La forma complicada innecesaria es iterar sobre cada campo:
Pero solo
sprintf
$1
y listo.fuente
En Awk puede usar un "*" para generar una cadena dinámica de formato printf.
Si ya conoce la longitud, puede pasar la longitud del campo para la primera columna con -v.
Nota: si no sabía cuál es la longitud de la primera columna, puede almacenar los valores en una matriz y luego encontrar la longitud máxima de la columna en el camino e imprimirla en el bloque FIN.
fuente