解析同一行上具有嵌套分隔符的文本文件

解析同一行上具有嵌套分隔符的文本文件

我想解析 btrfs 放置在名为 .btrfs 的文件中的 btrfs 清理统计信息/var/lib/btrfs/scrub.status.<uuid>。该文件实际上由键/值对组成,其中键和值由分号分隔,元组由竖线(“|”)字符分隔:

scrub status:1
b5872f47-c87e-47ac-b036-4f2725cf6dc6:1|data_extents_scrubbed:4996799|tree_extents_scrubbed:1436139|data_bytes_scrubbed:156663988224|tree_bytes_scrubbed:23529701376|read_errors:0|csum_errors:0|verify_errors:0|no_csum:733729|csum_discards:0|super_errors:0|malloc_errors:0|uncorrectable_errors:0|corrected_errors:0|last_physical:202959224832|t_start:1597847400|t_resumed:0|duration:67|canceled:0|finished:1

最后,我想在单独的行上发出每个键/值对,例如(这将用作 Prometheus 指标):

scrub status 1
data_extents_scrubbed 4996799
tree_extents_scrubbed 1436139
[...]

我已经尝试使用sed/完成这种嵌套解析awk,但到目前为止都失败了。

非常感谢任何如何实现这一目标的提示!

答案1

  • 任何 sed:

    sed 's/:/ /g;s/|/\
    /g' file
    
  • GNU sed:

    sed 's/:/ /g;s/|/\n/g' file
    

在这里,我们:用空格更改每个内容|,用换行符更改每个内容。

使用 awk,您可以将记录分隔符设置为管道字符,然后:用空格替换。

awk 'BEGIN{RS="|"}{gsub(":"," ");print}' file

答案2

使用用于多字符 RS 的 GNU awk:

$ awk -v RS='[|]|\n$' -F':' '{$1=$1}1' file
scrub status 1
b5872f47-c87e-47ac-b036-4f2725cf6dc6 1
data_extents_scrubbed 4996799
tree_extents_scrubbed 1436139
data_bytes_scrubbed 156663988224
tree_bytes_scrubbed 23529701376
read_errors 0
csum_errors 0
verify_errors 0
no_csum 733729
csum_discards 0
super_errors 0
malloc_errors 0
uncorrectable_errors 0
corrected_errors 0
last_physical 202959224832
t_start 1597847400
t_resumed 0
duration 67
canceled 0
finished 1

除此之外,与仅将 RS 设置为 的 awk 解决方案相比|,上面的解决方案不会在其输出末尾打印虚假的空行。

答案3

尝试:

$ awk -F'|' '{for (i=1;i<=NF;i++) {sub(/:/, " ", $i); print $i}}' file
scrub status 1
b5872f47-c87e-47ac-b036-4f2725cf6dc6 1
data_extents_scrubbed 4996799
tree_extents_scrubbed 1436139
data_bytes_scrubbed 156663988224
tree_bytes_scrubbed 23529701376

怎么运行的:

  • -F'|'将字段分隔符设置为|

  • {for (i=1;i<=NF;i++) {sub(/:/, " ", $i); print $i}}循环遍历每个字段,替换空白:并打印该字段。

答案4

这不是tr转换字符最快的方法吗?

$ <file tr ':|' ' \n'

scrub status 1
b5872f47-c87e-47ac-b036-4f2725cf6dc6 1
data_extents_scrubbed 4996799
tree_extents_scrubbed 1436139
data_bytes_scrubbed 156663988224
tree_bytes_scrubbed 23529701376
read_errors 0
csum_errors 0
verify_errors 0
no_csum 733729
csum_discards 0
super_errors 0
malloc_errors 0
uncorrectable_errors 0
corrected_errors 0
last_physical 202959224832
t_start 1597847400
t_resumed 0
duration 67
canceled 0
finished 1

当然,tr仅适用于一字节字符。对于:和来说这不是问题|

sed 的等效项(可以使用多字节字符 (GNU/ATT))是:

<file sed 'y/:|/ \n/'

相关内容