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

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

使用提供的示例,请尝试以下操作:

fpgainfo bmc | sed -E '1d; s/^([[:space:]]*[[:digit:]]+)[[:space:]]*//; s/[[:space:]]+:[[:space:]]+/,/' > fp.csv
  • 1d跳过第一行
  • s/^([[:space:]]*[[:digit:]]+)[[:space:]]*//删除前导序列号
  • s/[[:space:]]+:[[:space:]]+/,/替换冒号及其周围带逗号的空白

使用awk解决问题有不同的方法。

awk -F ' *: *' 'NR>1 { sub(/^([0-9 ]*) */,"");
if(heading) { heading=heading ","; data=data ","}
heading=heading $1; data = data $2
}
END {print heading; print data}' inputfile

使用问题中显示的输入,打印

Object Id,PCIe s,Device Id,Numa Node,Ports Num,Bitstream Id,Bitstream Version,Pr Interface Id,Board Power,12V Backplane Current,12V Backplane Voltage,1.2V Voltage,1.8V Voltage,3.3V Voltage,FPGA Core Voltage,FPGA Core Current,FPGA Die Temperature,Board Temperature,QSFP0 Supply Voltage,QSFP0 Temperature,12V AUX Current,12V AUX Voltage,QSFP1 Supply Voltage,QSFP1 Temperature,PKVL0 Core Temperature,PKVL0 SerDes Temperature,PKVL1 Core Temperature,PKVL1 SerDes Temperature
0xF000000,b,0x0b30,1,01,0x23000110030506,0.2.3,f3c99413-5081-4aad-bced-07eb84a6d0bb,58.11 Watts,2.43 Amps,12.14 Volts,1.19 Volts,1.81 Volts,3.27 Volts,0.90 Volts,12.28 Amps,58.50 Celsius,43.00 Celsius,0.00 Volts,0.00 Celsius,2.35 Amps,12.18 Volts,N/A,N/A,0.00 Celsius,0.00 Celsius,72.00 Celsius,73.50 Celsius

说明:

  • -F ' *: *'字段分隔符是:,包含任意数量的前导空格和尾随空格
  • NR>1对除第一行外的所有行执行{ ...}中的命令
  • sub(/^([0-9 ]*) */,"");该行末尾括号中的任何前导数字
  • if(heading) { heading=heading ","; data=data ","}如果标题不为空,则在标题和数据后加一个逗号,即除了第一个值之前,我们用逗号作为分隔符
  • heading=heading $1; data = data $2将第一个字段附加到标题,将第二个字段附加至数据
  • END {print heading; print data}在末尾打印标题和数据

我只用GNUawk测试了这个,它应该是Linux上awk的默认版本。

向下滚动到最后一段以获取我的最佳推荐。这提供了一些你试图在得出结论之前解释错误的背景。

在你的尝试中,只有中间的一个做了任何有用的或语法定义明确的事情——但sed语法仍然是错误的;您需要使用不同的分隔符或反斜杠regex中的文字斜杠才能使其工作。

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

我可能更喜欢Awk。如果你知道另一种脚本语言,或者正计划开始学习一种(例如Python(,那么你可能会选择它;但Awk很简单,你可以在半小时内学会其中的大部分。

不管怎样,周围的shell脚本看起来都是一样的;您需要运行您的命令并将其输出管道传输到something,它知道如何将在标准输入中接收的行转换为您想要的格式。

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(。这不一定工作量少,但它将更加健壮,因为格式是有文档记录的,指定得很好,并且是为编程操作而设计的。

这可能对你有用(GNU sed(:

sed -E '1{x;s/^/n/;x};/^(/!d
G;s/^(....).*: (.*)n(.*)n(.*)/3,1n4,2/;h;$!d;s/.(.*n)./1/' file

用换行符填充保留空间(列在换行符的左边,值在右边(。

垃圾邮件不需要的行。

附加保留空间,并将当前行的列和值替换为累积的列/值。

将累积的列/值复制到保留空间。

删除除最后一行以外的所有行。

删除逗号伪影并打印结果。


相同的解决方案,但适用于实际标题:

sed -E '1{x;s/^/n/;x};/^(/!d
G;s/^.....(.*S)s*: (.*)n(.*)n(.*)/3,1n4,2/;h;$!d;s/.(.*n)./1/' file

对于带括号的标题:

sed -E '1{x;s/^/n/;x};/^(/!d
G;s/^(.*S)s*: (.*)n(.*)n(.*)/3,1n4,2/;h;$!d;s/.(.*n)./1/' file

相关内容

  • 没有找到相关文章

最新更新