awk 将 TSV 表转换为网格表

awk 将 TSV 表转换为网格表

我想将以制表符作为分隔符的文本表(即基本上是 TSV 文件)转换为所有边框(内部和外部)上都有线条且文本换行的网格表。

下面是输入

   TrackId         peerId                                             Cause                                     Count
ESS_RSM         pra4.pra.pnc100.tpp240.6pppsetwork.prg             40009 Response is not received from server   1401
ESS_RSM         pra5.pra.pnc100.tpp240.6pppsetwork.prg             40009 Response is not received from server   1398
ESS_RSM         pra3.pra.pnc100.tpp240.6pppsetwork.prg             40009 Response is not received from server   1347
ESS_RSM         pra1.pra.pnc100.tpp240.6pppsetwork.prg             40009 Response is not received from server   1412
ESS_RSM         pra2.pra.pnc100.tpp240.6pppsetwork.prg             40009 Response is not received from server   1355
ESS_RSM         pra6.pra.pnc100.tpp240.6pppsetwork.prg             40009 Response is not received from server   1416

大片的空白是制表符; “未从服务器收到响应”中的空白是空格。输出应如下所示:

 ┌────────┬────────────────────────────────────────┬────────────────────────────┬────────┐
 │TrackId │ peerId                                 │ Cause                      │ Count  │
 ├────────┼────────────────────────────────────────┼────────────────────────────┼────────┤
 │ESS_RSM │ pra4.pra.pnc100.tpp240.6pppsetwork.prg │ 40009 Response is not      │  1,401 │
 │        │                                        │ received from server       │        │
 ├────────┼────────────────────────────────────────┼────────────────────────────┼────────┤
 │ESS_RSM │ pra5.pra.pnc100.tpp240.6pppsetwork.prg │ 40009 Response is not      │  1,398 │
 │        │                                        │ received from server       │        │
 ├────────┼────────────────────────────────────────┼────────────────────────────┼────────┤
 │ESS_RSM │ pra3.pra.pnc100.tpp240.6pppsetwork.prg │ 40009 Response is not      │  1,347 │
 │        │                                        │ received from server       │        │
 ├────────┼────────────────────────────────────────┼────────────────────────────┼────────┤
 │ESS_RSM │ pra1.pra.pnc100.tpp240.6pppsetwork.prg │ 40009 Response is not      │  1,412 │
 │        │                                        │ received from server       │        │
 ├────────┼────────────────────────────────────────┼────────────────────────────┼────────┤
 │ESS_RSM │ pra2.pra.pnc100.tpp240.6pppsetwork.prg │ 40009 Response is not      │  1,355 │
 │        │                                        │ received from server       │        │
 ├────────┼────────────────────────────────────────┼────────────────────────────┼────────┤
 │ESS_RSM │ pra6.pra.pnc100.tpp240.6pppsetwork.prg │ 40009 Response is not      │  1,416 │
 │        │                                        │ received from server       │        │
 └────────┴────────────────────────────────────────┴────────────────────────────┴────────┘

或者可能

TrackId │ peerId                         │ Cause                                │ Count   │
────────┼────────────────────────────────┼──────────────────────────────────────┼─────────┤
        │ pra4.pra.pnc100.tpp240.6pppset │ 40009 Response is not received from  │         │
ESS_RSM │ work.prg                       │ server                               │   1,401 │
────────┼────────────────────────────────┼──────────────────────────────────────┼─────────┤
        │ pra5.pra.pnc100.tpp240.6pppset │ 40009 Response is not received from  │         │
ESS_RSM │ work.prg                       │ server                               │   1,398 │
────────┼────────────────────────────────┼──────────────────────────────────────┼─────────┤
        │ pra3.pra.pnc100.tpp240.6pppset │ 40009 Response is not received from  │         │
ESS_RSM │ work.prg                       │ server                               │   1,347 │
────────┼────────────────────────────────┼──────────────────────────────────────┼─────────┤
        │ pra1.pra.pnc100.tpp240.6pppset │ 40009 Response is not received from  │         │
ESS_RSM │ work.prg                       │ server                               │   1,412 │
────────┼────────────────────────────────┼──────────────────────────────────────┼─────────┤
        │ pra2.pra.pnc100.tpp240.6pppset │ 40009 Response is not received from  │         │
ESS_RSM │ work.prg                       │ server                               │   1,355 │
────────┼────────────────────────────────┼──────────────────────────────────────┼─────────┤
        │ pra6.pra.pnc100.tpp240.6pppset │ 40009 Response is not received from  │         │
ESS_RSM │ work.prg                       │ server                               │   1,416 │
────────┴────────────────────────────────┴──────────────────────────────────────┴─────────┘

我尝试了下面的代码,但输出不是我想要的。

awk '{print "<table>"} {print "<tr>"; for(i=1;i<=NF;i++) print "|" $i "|";print "|"} END {PRINT "|"}' file

答案1

使用一些古老的 Unix 实用程序,

#!/bin/sh
{
        printf '%s\n' '' .TS 'allbox;LLLL,LLLR.'
        awk -v sq="'" '
            BEGIN { FS = OFS = "\t"; fmt = "%" sq "d" }
            NR==1 { print }
            NR>1  {
                        print $1, "T{"
                        print          $2
                        print             "T}", "T{"
                        print                        $3
                        print                           "T}", sprintf(fmt, $4)
                  }
            ' "$@"
        printf '%s\n' .TE '.pl 0'
} | tbl | nroff 2> /dev/null

解释:

  • nroff是古老的 Unix 文本处理器。例如,它将采取
    Lorem ipsum dolor sit amet, consectetur adipiscing elit,
    sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
    Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi
    ut aliquip ex ea commodo consequat.
    Duis aute irure dolor in reprehenderit
    in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
    Excepteur sint occaecat cupidatat non proident,
    sunt in culpa qui officia deserunt mollit anim id est laborum.
    
    作为输入,并产生
    Lorem  ipsum  dolor sit amet, consectetur adipiscing elit, sed do
    eiusmod tempor incididunt ut labore et dolore magna  aliqua.   Ut
    enim  ad  minim veniam, quis nostrud exercitation ullamco laboris
    nisi ut aliquip ex ea commodo consequat.  Duis aute  irure  dolor
    in  reprehenderit in voluptate velit esse cillum dolore eu fugiat
    nulla pariatur.  Excepteur sint occaecat cupidatat non  proident,
    sunt in culpa qui officia deserunt mollit anim id est laborum.
    
    作为输出。
  • tblnroff是一个支持(你猜对了)表格生成的前端。
  • .TS是“表开始”。
  • allbox相当明显:在每个单元格周围画一个框。
  • LLLL表示第一行中的所有单元格都是左对齐的; LLLR意味着第四个单元格对于所有后续行都是右对齐的。我想这就是您从示例输出中想要的结果。
  • -v sq="'"创建一个名为的变量,sq 其值为单引号。这是在 awk 程序中使用单引号的方法之一,建议在GNU Awk 用户指南
  • 设置FS为制表符,因为输入是 TSV。设置 OFS为制表符,因为这是所tbl期望的(默认情况下)。
  • fmt = "%" sq "d"设置fmt%'d,可与 一起使用来[s]printf 输出带有千位分隔符的整数。 (我假设你想要这个,因为你展示了它。)
  • 不加修改地传递第一行(标题)。
  • 对于所有其他行(数据),使用T{T}标记$2进行 $3 文本换行。 (我假设您只需要第二列和第三列,因为第一列和第四列仅包含短字符串。)打印 的值,$4每三个数字插入一个逗号。
  • .TE是“桌尾”。
  • .pl是页面长度。这是一个拼凑的东西。默认情况下,nroff将用空行填充其输出,以使整体输出成为 66 行的倍数。通过将页面长度设置为零,我们可以抑制这种情况。
  • 上述 ( printf, awk 和 printf) 的输出通过管道输送到tbl 和 nroff
  • 尽管标准输出是合理的,但我还是遇到了很多出现错误消息的问题,所以我将 stderr 发送到了 bitbucket。如果你得到奇怪的结果,你应该做的第一件事就是摆脱 stderr 重定向并查看错误消息(尽管它们可能不是很有帮助)。

指示:

  • 将上面的代码放入一个文件中。例如,调用它gman
  • $ chmod +x gman
    
    使其可执行。
  • 如果您的数据位于文件中(例如,名为shap),请执行以下操作
    $ ./gman shap
    
    您可能希望将输出重定向到文件:
    $ ./gman shap > grid_table
    
  • 如果您在第一列中获取所有数据,则意味着您的输入文件中实际上没有制表符(只是空格)。编辑它以用制表符替换空白(空格)。
  • 如果您的数据是由其他程序生成/产生的,例如数据库查询,您可以这样做
    $ db_query > tmp
    $ ./gman tmp
    
    (然后可选rm tmp,如果您不需要它做其他任何事情),或者只是
    $ db_query | ./gman
    
  • 如果您将文件移动(或复制)gman到搜索路径中的目录,则只需键入gman(无需./)。有一个 很多有关于此的文档;如果你搜索的话很容易找到。

例如,对于问题中显示的输入,我得到

┌───────────┬─────────────────────────────────┬───────────────┬───────┐
│   TrackId │ peerId                          │ Cause         │ Count │
├───────────┼─────────────────────────────────┼───────────────┼───────┤
│ESS_RSM    │ pra4.pra.pnc100.tpp240.6pppset‐ │ 40009     Re‐ │ 1,401 │
│           │ work.prg                        │ sponse is not │       │
│           │                                 │ received from │       │
│           │                                 │ server        │       │
├───────────┼─────────────────────────────────┼───────────────┼───────┤
│ESS_RSM    │ pra5.pra.pnc100.tpp240.6pppset‐ │ 40009     Re‐ │ 1,398 │
│           │ work.prg                        │ sponse is not │       │
│           │                                 │ received from │       │
│           │                                 │ server        │       │
├───────────┼─────────────────────────────────┼───────────────┼───────┤
│ESS_RSM    │ pra3.pra.pnc100.tpp240.6pppset‐ │ 40009     Re‐ │ 1,347 │
│           │ work.prg                        │ sponse is not │       │
│           │                                 │ received from │       │
│           │                                 │ server        │       │
├───────────┼─────────────────────────────────┼───────────────┼───────┤
│ESS_RSM    │ pra1.pra.pnc100.tpp240.6pppset‐ │ 40009     Re‐ │ 1,412 │
│           │ work.prg                        │ sponse is not │       │
│           │                                 │ received from │       │
│           │                                 │ server        │       │
├───────────┼─────────────────────────────────┼───────────────┼───────┤
│ESS_RSM    │ pra2.pra.pnc100.tpp240.6pppset‐ │ 40009     Re‐ │ 1,355 │
│           │ work.prg                        │ sponse is not │       │
│           │                                 │ received from │       │
│           │                                 │ server        │       │
├───────────┼─────────────────────────────────┼───────────────┼───────┤
│ESS_RSM    │ pra6.pra.pnc100.tpp240.6pppset‐ │ 40009     Re‐ │ 1,416 │
│           │ work.prg                        │ sponse is not │       │
│           │                                 │ received from │       │
│           │                                 │ server        │       │
└───────────┴─────────────────────────────────┴───────────────┴───────┘

作为输出。有一些技巧可以使列(例如,第三列)更宽;让我知道你想知道什么。

警告:当您运行此命令时,tbl 将会 nroff

  1. 读取所有数据,
  2. 将其存储在内存和/或临时文件中,
  3. 计算列宽,然后
  4. 输出所有数据。

如果你有很多的数据,您可能会溢出临时存储的限制,并且命令将失败。您可以通过将输入分解为较小的文件来获得可用的结果。

警告:如果您的文件包含T{T}、或 以句点 (.) 或单引号 ('),你可能会得到奇怪的结果。

答案2

awk '{$1=$1"|";$2=$2"|";$NF="|"$NF}1' input.txt | awk -F\| 'BEGIN{print "<table border=1>"}{gsub("\\|","</td><td>");print"<tr><td>"$0"</td></tr>"}END{print "</table>"}' > output.html

第一个 awk 用于通过 | 分隔值

第二个 awk 用于将值格式化为 HTML 表

相关内容