首页 > 解决方案 > linux命令输出一个csv文件(里面有不同的格式)

问题描述

命令输出:

//****** BMC SENSORS ******//
Object Id                     : 0xF000000
PCIe s:b:d.f                  : 0000:b2:00.0
Device Id                     : 0x0b30
Numa Node                     : 1
Ports Num                     : 01
Bitstream Id                  : 0x23000110030506
Bitstream Version             : 0.2.3
Pr Interface Id               : f3c99413-5081-4aad-bced-07eb84a6d0bb
( 1) Board Power              : 58.11 Watts
( 2) 12V Backplane Current    : 2.43 Amps
( 3) 12V Backplane Voltage    : 12.14 Volts
( 4) 1.2V Voltage             : 1.19 Volts
( 6) 1.8V Voltage             : 1.81 Volts
( 8) 3.3V Voltage             : 3.27 Volts
(10) FPGA Core Voltage        : 0.90 Volts
(11) FPGA Core Current        : 12.28 Amps
(12) FPGA Die Temperature     : 58.50 Celsius
(13) Board Temperature        : 43.00 Celsius
(14) QSFP0 Supply Voltage     : 0.00 Volts
(15) QSFP0 Temperature        : 0.00 Celsius
(24) 12V AUX Current          : 2.35 Amps
(25) 12V AUX Voltage          : 12.18 Volts
(37) QSFP1 Supply Voltage     : N/A
(38) QSFP1 Temperature        : N/A
(44) PKVL0 Core Temperature   : 0.00 Celsius
(45) PKVL0 SerDes Temperature : 0.00 Celsius
(46) PKVL1 Core Temperature   : 72.00 Celsius
(47) PKVL1 SerDes Temperature : 73.50 Celsius

我不需要第一行,序列号。希望左侧部分作为标题,右侧部分分别作为CSV中每个标题的列。

我尝试以不同的方式使用 sed -

sed ///****** BMC SENSORS ******/// fpgainfo bmc

fpgainfo bmc | sed ///****** BMC SENSORS ******/// >> ./fp.csv 

sed (1),(2),(3),(4),(6),(8),(10),(11),(12),(13),(14),(15),(24),(25),(37),(38),(44),(45),(46),(47)` fpgainfo bmc

但并没有达到我的预期。请帮助我实现同样的目标。

标签: linuxcsvunixsed

解决方案


向下滚动到最后一段以获得我的最佳建议。这提供了一些关于您尝试的背景,只是为了在得出结论之前解释什么是错误的。

在你的尝试中,只有中间的那个做了一些远程有用或语法定义明确的事情——但sed语法仍然是错误的;您需要使用不同的定界符或反斜杠正则表达式中的文字斜杠才能正常工作。

但这sed可能不是一个好的工具;它的处理模型基本上被限制为一次检查一个输入行。你可以让它执行更具挑战性的处理,但对于初学者来说,这绝对不是一个好的第一个练习。

为此,我可能更喜欢 Awk。如果您知道另一种脚本语言,或者计划开始学习一种(例如 Python),则可能会选择它;但是 awk 足够简单,你可以在半小时内学会它的大部分内容。

无论如何,周围的 shell 脚本看起来都一样;你会想要运行你的命令并将它的输出传递给知道如何将它在标准输入上接收到的行转换为你想要的格式的东西。

fpgainfo bmc | awk ...

那么,这里是一个简单的 Awk 脚本,用于提取(我认为您想说的是)您想要的字段到 CSV 文件中,字段名称位于值之前的标题行中。

awk 'BEGIN { sep=""; n=0 }
  /^\( *[1-9][0-9]*\)/ {
    # Parse out data; trim trailing whitespace
    key = substr($0, 6, 25)
    sub(/ +$/, "", key)
    value = substr($0, 33)
    sub(/ +$/, "", value)

    # Normalize index
    sub(/^\( +/, "")
    if ($1 ~ /^[123468]|1[12345]|2[45]|3[78]|4[4567])\)/) {
      printf("%s%s", sep, key)
      sep = ","
      v[++n] = value }
  }
  END { printf "\n"; sep=""; 
    for(i=1; i<=n; ++i) {
      printf("%s%s", sep, v[i])
      sep = "," }
    printf "\n"
  }'

演示:https ://ideone.com/BwRN72

但这仍然很脆弱,因为它取决于您显示的输出完全代表我们需要处理的所有内容的假设。很容易出现这样的情况,即程序会为了易读性而换行长线,或者根据终端的大小调整列宽。

我不熟悉,fpgainfo但大多数现代工具都可以选择直接生成机器可读的输出(JSON、YAML、XML 等);如果可以的话,它通常比手工制作解析器来处理像这样的肮脏的人类可读格式要好得多。快速谷歌搜索让我得到https://opae.github.io/0.13.0/docs/fpga_tools/fpgainfo/fpgainfo.html其中提到了一个--json选项 - 可能会改为(并注意例如jq可以进一步将其转换为适当的 CSV一个简单的选项)。它的工作量不一定会减少,但它会变得更加健壮,因为格式已记录、明确指定并且专为编程操作而设计。


推荐阅读