bash 将行转换为表格格式的列

Posted

技术标签:

【中文标题】bash 将行转换为表格格式的列【英文标题】:bash convert rows into columns in table format 【发布时间】:2022-01-22 14:28:12 【问题描述】:

我正在尝试将行转换为表格格式的列。

Server Name            : dev1-151vd
  Status                 : DONE
  Begin time             : 2021-12-20 04:30:05.458719-05:00
  End time               : 2021-12-20 04:33:15.549731-05:00

  Server Name            : dev2-152vd
  Status                 : DONE
  Begin time             : 2021-12-20 04:30:05.405746-05:00
  End time               : 2021-12-20 04:30:45.212935-05:00

我使用以下 awk 脚本将行转换为列

awk -F":" -v n=4 \
  'BEGIN  x=1; c=0; 
  ++c <= n && x == 1 print $1; buf = buf $2 "\n";
       if(c == n) x = 2; printf buf next;
   !/./c=0;next
    c <=n printf "%4s\n", $2' temp1.txt | \
   paste - - - - | \
   column -t -s "$(printf "\t")"




Server Name                Status                      Begin time                 End time
 dev1-151vd                  DONE                       2021-12-20 04               2021-12-20 04
 dev2-152vd                  DONE                       2021-12-20 04              2021-12-20 04

以上 o/p 没有正确的开始时间和结束时间,请告诉我如何正确设置格式以便正确打印时间。

【问题讨论】:

永远不要对任何输入使用printf buf,因为当您的输入包含像%s 这样的printf 格式化字符时,它会神秘地失败,请始终使用printf "%s", buf 【参考方案1】:
$ cat tst.awk
BEGIN  OFS="\t" 
NF 
    if ( ++fldNr == 1 ) 
        recNr++
        rec = ""
    
    tag = val = $0
    sub(/[[:space:]]*:.*/,"",tag)
    sub(/[^:]+:[[:space:]]*/,"",val)
    hdr = hdr (fldNr>1 ? OFS : "") tag
    rec = rec (fldNr>1 ? OFS : "") val
    next


    if ( recNr == 1 ) 
        print hdr
    
    print rec
    fldNr = 0

END  if (fldNr) print rec 

$ awk -f tst.awk file | column -s$'\t' -t
Server Name  Status  Begin time                        End time
dev1-151vd   DONE    2021-12-20 04:30:05.458719-05:00  2021-12-20 04:33:15.549731-05:00
dev2-152vd   DONE    2021-12-20 04:30:05.405746-05:00  2021-12-20 04:30:45.212935-05:00

无论您输入的每条记录有多少行,以及您是否有其他 :s 或 %ss 或其他任何内容,上述方法都将起作用。

【讨论】:

【参考方案2】:

查看此脚本:

awk -F": " -v n=4 \
  'BEGIN  x=1; c=0; 
  ++c <= n && x == 1 print $1; buf = buf $2 "\n";
       if(c == n) x = 2; printf buf next;
   !/./c=0;next
    c <=n printf "%4s\n", $2' 20211222.txt | \
   paste - - - - | \
   column -t -s "$(printf "\t")"

输出:

Server Name                Status                     Begin time                        End time
dev1-151vd               DONE                       2021-12-20 04:30:05.458719-05:00  2021-12-20 04:33:15.549731-05:00
dev2-152vd               DONE                       2021-12-20 04:30:05.405746-05:00  2021-12-20 04:30:45.212935-05:00

说明: 在 awk 中,-F 选项表示字段分隔符。在您的代码中,您使用冒号将列彼此分隔。但是,在您的输入中,有些行有超过 1 个冒号(即仅您的时间戳字段就有 3 个冒号),因此 awk 将它们解释为有 5 列。

解决方案是在字段分隔符 (": ") 中添加一个空格,因为您的输入在第一个冒号之后和第二列之前确实有一个空格。

【讨论】:

以上是关于bash 将行转换为表格格式的列的主要内容,如果未能解决你的问题,请参考以下文章

需要将行转换为oracle中相似ID的列

将行转换为涉及日期的列

将行值转换为火花数据框中的列数组

如何将行转换为按行数创建标题的列

如何使用枢轴将行转换为postgres中的列?让我来计算一下

Postgres - 将行转换为两个表中的列