如何使用 awk 打印一个漂亮的表格格式及其列(NF)和行号(NR)?

如何使用 awk 打印一个漂亮的表格格式及其列(NF)和行号(NR)?

样本数据

wolf@linux:~$ awk {print} file.txt 
a b
b c
c d
wolf@linux:~$ 

由于数据非常小,因此很容易做到这一点。

wolf@linux:~$ awk 'BEGIN {print "  " 1 " " 2} {print NR,$0}' file.txt
  1 2
1 a b
2 b c
3 c d
wolf@linux:~$ 

对于更大的数据有类似的解决方案吗?我正在考虑使用类似for loopon BEGIN {print " " 1 " " 2}part 的东西,而不是手动打印标题

答案1

BEGIN部分在打开任何输入文件之前执行,因此运行 a for loopThere 不会有任何好处,因为输入的第一行尚未被读取,因此您不知道有多少字段要循环。除非你添加一个getline,但这完全是另一堆蠕虫(参见http://awk.freeshell.org/AllAboutGetline)。

我将awk创建字段内容,然后将column其格式化为间距,例如:

$ awk '
    NR==1 { for (i=1; i<=NF; i++) printf " %s", i; print "" }
    { print NR, $0 }
' file  | column -s' ' -t
   1  2
1  a  b
2  b  c
3  c  d

如果您的输入文件字段之间可能有多个空格或制表符,则只需将 awk 脚本的最后一行从 更改{ print{ $1=$1; print.

答案2

我们可以使用 groff 包装器生成表tbl,它生成 groff 代码以根据所需的架构生成表。

在这里,根据数据,我们动态生成 tbl 实用程序的代码,该代码将使用 awk 实用程序生成 groff 排版实用程序的代码:

< file \
awk '
  BEGIN {
    OFS = "@"
    print ".TS"
    print "box,tab(", ");"
  }

  !NF {next}

  NR==1 {
    fx(" ", "c", "c", ".")
    fx(OFS) 
  }

  { $1 = NR OFS $1 };1

  END { print ".TE" }

  function fp(str, sep) {
    printf "%s%s", sep, str
  }

  function fx(sep, a, b, c,   i) {
    fp(a)
    for (i=1; i<=NF; i++)
      fp(b""?b:i, sep)
    fp("\n", c)
  }
' - | tbl - | groff -Tascii | grep .

输出:

+----------+
|    1   2 |
|1   A   B |
|2   B   C |
|3   C   D |
+----------+

答案3

您可以使用 for 循环来迭代字段。 NR 是当前行号,NF 是该特定行上的字段数。

{   printf ("%4d", NR);
    for (f = 1; f <= NF; ++f) printf (" %-6s", $f);
    printf ("\n");
}

对于标题,您需要等待第一行才能发现需要标记多少列。所以这就是前面的代码。请注意,它将 f 本身打印为标签,而不是代表字段内容的 $f。

NR == 1 {   printf ("%4d", NR);
    for (f = 1; f <= NF; ++f) printf (" %-6s", f);
    printf ("\n");
}

您需要找到最大字段宽度以保持对齐。每个 %-6 表示“一个字符串字段,左对齐,并用空格填充最多 6 个字符”。

编辑:对于更高级的版本,您可以将所有数据存储在二维数组中,按 [NR, NF] 索引,并将它们输出到 END 块中。然后你还可以做两件事:

(1) 对于每一列,找到任何单元格的最大宽度,并使用该列的实际宽度修复 %-10s 格式。

(2) 对于每一列,如果其全部为数值,则修复其 %s 以右对齐值。

相关内容