使用printf自动进行文本格式化(基于每列的最大长度)

时间:2017-09-27 15:00:33

标签: awk

输入数据有n列用“|”分隔比如下面的例子:

121|234234|5345|2342342342432423
1|2342|2|2342
234|23|343|34214222

如何找到每列的最大长度,稍后在输入的printf格式化中使用它,即使将来更改输入数据也会有效?

在命令中如下:

awk -F'|' '..... {printf“% - longestincol1 s% - longestincol2 s% - longestincol3 s%-s \ n”,$ 1 ,$ 2,$ 3,$ 4}'....

2 个答案:

答案 0 :(得分:1)

<强>输入:

$ cat infile
121|234234|5345|2342342342432423
1|2342|2|2342
234|23|343|34214222

<强>输出:

使用 printf("%*s%s"

awk 'BEGIN{FS=OFS="|"}FNR==NR{for(i=1; i<=NF;i++)wd[i]=wd[i]>length($i)?wd[i]:length($i);next}{for(i=1; i<=NF; i++)printf("%*s%s",wd[i],$i,(i<NF?OFS:ORS))}' infile infile
121|234234|5345|2342342342432423
  1|  2342|   2|            2342
234|    23| 343|        34214222

使用 printf("%-*s%s"

awk 'BEGIN{FS=OFS="|"}FNR==NR{for(i=1; i<=NF;i++)wd[i]=wd[i]>length($i)?wd[i]:length($i);next}{for(i=1; i<=NF; i++)printf("%-*s%s",wd[i],$i,(i<NF?OFS:ORS))}' infile infile
121|234234|5345|2342342342432423
1  |2342  |2   |2342            
234|23    |343 |34214222   

更好的可读性:

awk '
     BEGIN{
            FS=OFS="|"
     }
     FNR==NR{
          for(i=1; i<=NF;i++)
             wd[i]=wd[i]>length($i)?wd[i]:length($i);
             next
     }
     {
          for(i=1; i<=NF; i++)
              printf("%*s%s",wd[i],$i,(i<NF?OFS:ORS)); 

     }
   ' infile infile

<强>解释

Like C/C++指定为字符串

分配多少空间
  

*宽度未在格式字符串中指定,而是作为   必须的参数前面的附加整数值参数   格式化。

printf("%*s",5,"")

相同
printf("%5s", "");   

答案 1 :(得分:0)

如果你只想要一个漂亮的打印输出,你可以使用column例如

column -t -s'|' -o'|' file

但是,它并不完全符合您的printf格式。它做左对齐。

awk中

如果你想用awk做,你可以应用至少两种方法:

处理文件一次

你让awk经历一次输入,在循环期间计算最大宽度,保存内存中的所有行。最后,END{...}遍历数组进行打印。

处理文件两次

首先让awk浏览文件,只计算max-width,然后保存到变量中。在第二步,做格式打印。

我没有给出工作代码,但我希望我能清楚地回答。当你下次遇到类似的问题时,它也会有所帮助。