awk - 以3列格式打印输出

时间:2016-08-10 15:01:48

标签: bash awk

我有一个以下列格式显示的数据文本文件。

apropos c
awk nc
chsh c
date nc
grep nc
i3 nc
ip6tables nc

我正在尝试通过awk过滤此数据,以生成3列格式,类似于下面。

apropos          awk          chsh
date             grep         i3

我不需要关于该文件的第二列信息,但是想要第一列的干净且对齐的输出。我在其他地方找到了以下代码,并对其进行了一些修改以仅输出第一列数据。问题是由于使用标签而导致它未对齐。

awk '{printf (NR %3 == 0 )? $1 "\n" : $1"\t\t" }'

进行更多研究我通过awk的printf(即“%-10s”)找到了宽度的用法。唯一的问题是我不太确定如何将它整合到我的命令中以使它做我想做的事情。任何帮助将不胜感激,谢谢!

3 个答案:

答案 0 :(得分:4)

对于您来说,这可能比对10之类的任意字段宽度进行硬编码更有用:

$ awk '{ORS=(NR%3?FS:RS); print $1}' file | column -t
apropos    awk   chsh
date       grep  i3
ip6tables

或者如果您确实要从输出中删除ip6tables,如示例输入/输出中所示:

$ awk '{rec = rec OFS $1} !(NR%3){print rec; rec=""}' file | column -t
apropos  awk   chsh
date     grep  i3

如果你没有管道到column并且不想选择一些任意数字作为字段宽度,那么你需要awk来输入两次输入文件以确定每列的最大宽度首先打印前(见https://stackoverflow.com/a/38791539/1745001)。

第一个例子 - 在输入中运行任何不以换行符结尾的UNIX工具依赖于POSIX规范的未定义行为,所以如果column在{{1}之后缺少换行符时发出警告然后添加它:

ip6tables

答案 1 :(得分:1)

您可以使用以下awk | column管道:

awk '{sep=NR%3?OFS:ORS;printf "%s%s", $1, sep}END{if(NR%3)print ""}' a.txt  \
  | column  -t

注意:由于(至少)BSD版本的column命令会打印警告:

column: line too long

并省略最后一行,以防列表中的行数不是列数的倍数,在这种情况下,您需要在最后一个元素之后打印换行符。

答案 2 :(得分:1)

非awk解决方案

$ cut -d' ' -f1 <file | paste - - - | column -t

apropos    awk   chsh
date       grep  i3
ip6tables

pr

$ cut -d' ' -f1 <file | pr -3at

apropos                 awk                     chsh
date                    grep                    i3
ip6tables