【问题标题】:merge columns of line n+1 to line n将第 n+1 行的列合并到第 n 行
【发布时间】:2018-06-13 11:11:10
【问题描述】:

iostat 可以显示持久设备名称(带有 -j id)而不是内核设备名称(例如 sda),但这也意味着选项 -h 用于“人类可读”输出。 这会产生这样的输出(一行包含永久磁盘名称,例如 HOMES 或 DATADISK,下一行包含该磁盘的值)。

(在我的示例中,我将 iostat 的输出通过管道传输到 awk '// {print strftime("%Y-%m-%d %H:%M:%S"),$0}' 以获得时间戳每行的开头):

2018-06-13 11:57:03 HOMES
2018-06-13 11:57:03                   0.00     0.00    0.00    0.50     0.00     2.00     8.00     0.00    1.00    0.00    1.00   1.00   0.05
2018-06-13 11:57:03 ARCHIVEDISK
2018-06-13 11:57:03                   0.00     0.00    0.00    0.50     0.00     2.00     8.00     0.00    0.00    0.00    0.00   0.00   0.00
2018-06-13 11:57:03 DATADISK
2018-06-13 11:57:03                   0.00     0.00   86.00    0.50   680.00     2.00    15.77     0.12    1.40    1.41    1.00   1.26  10.90
2018-06-13 11:57:05 HOMES
2018-06-13 11:57:05                   0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
2018-06-13 11:57:05 ARCHIVEDISK
2018-06-13 11:57:05                   0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
2018-06-13 11:57:05 DATADISK
2018-06-13 11:57:05                   0.00     0.00  122.00  116.00   976.00  1164.00    17.98     0.56    2.33    3.36    1.26   1.47  34.90

我怎样才能合并这些行所以我得到这个:

2018-06-13 11:57:03 HOMES             0.00     0.00    0.00    0.50     0.00     2.00     8.00     0.00    1.00    0.00    1.00   1.00   0.05
2018-06-13 11:57:03 ARCHIVEDISK       0.00     0.00    0.00    0.50     0.00     2.00     8.00     0.00    0.00    0.00    0.00   0.00   0.00
2018-06-13 11:57:03 DATADISK          0.00     0.00   86.00    0.50   680.00     2.00    15.77     0.12    1.40    1.41    1.00   1.26  10.90
2018-06-13 11:57:05 HOMES             0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
2018-06-13 11:57:05 ARCHIVEDISK       0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
2018-06-13 11:57:05 DATADISK          0.00     0.00  122.00  116.00   976.00  1164.00    17.98     0.56    2.33    3.36    1.26   1.47  34.90

【问题讨论】:

  • 修复产生此输出的 awk 命令而不是创建新的 awk 命令来处理现有的 awk 命令输出难道不是更好的方法吗?现在就像你在问射击后如何包扎你的脚 - 只是不要射击它......
  • 大部分输出由 iostat 完成。 awk 只是在行首添加日期/时间。当然,我可能可以实现例如第一个 awk 的 olivs 解决方案……但我更喜欢 2 个“简单”的 awk 命令而不是 1 个“更复杂”的命令……
  • 由于您不知道一个 awk 命令是什么,因此您不知道它是否比通过管道连接的 2 个 awk 命令更复杂。我希望它不那么复杂。

标签: linux shell awk scripting


【解决方案1】:

Perl 的救援:

perl -pe 'if ($. % 2) {
    chomp;
    $l = length;
} else {
    s/^.{19} */" " x (38 - $l)/e;
}' -- file
  • $. 包含输入行号
  • % 是取模运算符,即$. % 2 对第 1、3、5、7 行等返回 true。
  • /es/// 替换的替换部分解释为代码,这里它重复了一个空格 38 - $l 次,其中 $l 是上一行的长度(对齐数字)

【讨论】:

    【解决方案2】:

    awk,保持间距:

    awk '
        NR % 2 {label = $3; next}
        {print substr($0, 1, 19), label, substr($0, 22 + length(label))}
    ' file
    

    【讨论】:

      【解决方案3】:

      使用 awk:

      awk 'NF==3{n=$3;next}{for(i=NF;i>2;i--) $(i+1)=$i;$3=n}1' file | column -t
      

      awk 脚本在该行包含 3 个元素时获取名称。 对于所有其他行,它将所有元素移动一个位置,除了前 2 个。 最后一行被打印出来了。

      命令column 正在重新格式化以按列显示。

      【讨论】:

        【解决方案4】:

        如果 iostat 输出如下所示:

        $ cat file
        HOMES
                          0.00     0.00    0.00    0.50     0.00     2.00     8.00     0.00    1.00    0.00    1.00   1.00   0.05
        ARCHIVEDISK
                          0.00     0.00    0.00    0.50     0.00     2.00     8.00     0.00    0.00    0.00    0.00   0.00   0.00
        DATADISK
                          0.00     0.00   86.00    0.50   680.00     2.00    15.77     0.12    1.40    1.41    1.00   1.26  10.90
        HOMES
                          0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
        ARCHIVEDISK
                          0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
        DATADISK
                          0.00     0.00  122.00  116.00   976.00  1164.00    17.98     0.56    2.33    3.36    1.26   1.47  34.90
        

        那么您只需要 1 个小而简单的 awk 命令(使用cat file 代替下面的iostat):

        $ cat file | awk 'NR%2{dev=$0; next} {printf "%s %-18s %s\n", strftime("%F %T"), dev, substr($0,19)}'
        2018-06-22 10:34:09 HOMES              0.00     0.00    0.00    0.50     0.00     2.00     8.00     0.00    1.00    0.00    1.00   1.00   0.05
        2018-06-22 10:34:09 ARCHIVEDISK        0.00     0.00    0.00    0.50     0.00     2.00     8.00     0.00    0.00    0.00    0.00   0.00   0.00
        2018-06-22 10:34:09 DATADISK           0.00     0.00   86.00    0.50   680.00     2.00    15.77     0.12    1.40    1.41    1.00   1.26  10.90
        2018-06-22 10:34:09 HOMES              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
        2018-06-22 10:34:09 ARCHIVEDISK        0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
        2018-06-22 10:34:09 DATADISK           0.00     0.00  122.00  116.00   976.00  1164.00    17.98     0.56    2.33    3.36    1.26   1.47  34.90
        

        无需添加时间戳然后再次删除它们、不必要地调用 strftime、循环通过字段、管道、对“列”的调用,这会弄乱你原来的对齐方式,等等。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-02-17
          • 1970-01-01
          • 2014-02-28
          • 2019-01-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多