linux - 转换 key :value to CSV file

标签 linux awk scripting

我找到了以下用于将包含键值信息的文件转换为 CSV 文件的 bash 脚本:

awk -F ":" -v OFS="," '
BEGIN { print "category","recommenderSubtype", "resource", "matchesPattern", "resource", "value" }
function printline() {
print data["category"], data["recommenderSubtype"], data["resource"], data["matchesPattern"], data["resource"], data["value"]
}
{data[$1] = $2}
NF == 0 {printline(); delete data}
END {printline()}
' file.yaml

但是执行后,它只转换第一组数据(只转换前6行数据),像这样

category,recommenderSubtype,resource,matchesPattern,resource,value
COST,CHANGE_MACHINE_TYPE,instance-1,f1-micro,instance-1,g1-small

我的原始文件是这样的(1000行以上):

category:COST
recommenderSubtype:CHANGE_MACHINE_TYPE
resource:portal-1
matchesPattern:f1-micro
resource:portal-1
value:g1-small
category:PERFORMANCE
recommenderSubtype:CHANGE_MACHINE_TYPE
resource:old-3
matchesPattern:n1-standard-4
resource:old-3
value:n1-highmem-2

我是否缺少任何命令?

最佳答案

原始脚本的问题是这些行:

NF == 0 {printline(); delete data}
END {printline()}

第一行意思是:如果当前行没有记录就调用printline()。第二行表示在处理完所有数据后调用printline()

输入数据格式的困难在于它并不能很好地指示何时输出下一条记录。下面,我只是将脚本更改为每 6 条记录输出一次数据。如果可能存在重复键,输出标准可能是“所有字段已填充”或需要稍微不同编程的标准。

#!/bin/sh -e
awk -F ":" -v OFS="," '
BEGIN {
    records_in = 0
    print "category","recommenderSubtype", "resource", "matchesPattern", "resource", "value"
}
{
    data[$1] = $2
    records_in++
    if(records_in == 6) {
        records_in = 0;
        print data["category"], data["recommenderSubtype"], data["resource"], data["matchesPattern"], data["resource"], data["value"]
    }
}
' file.yaml

其他表扬

  • 我刚刚删除了 delete 语句,因为我不确定它的作用。 awk 的 POSIX 规范仅将其定义为删除单个数组元素。如果要删除整个数组,建议对元素进行循环。但是,如果所有字段始终存在,则不妨完全消除它。
  • 欢迎来到 SO(我也是新来的)。下次你问的时候,我建议将问题标记为 awk 而不是 bash 因为 AWK 实际上是这个问题中使用 bash 的脚本语言只负责用合适的参数调用 awk :)

关于linux - 转换 key :value to CSV file,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58597307/

相关文章:

file - 在文件中搜索字符串并输出行号

linux - 在下面的行中提取一个值并将结果与​​原始搜索词一起写入 (linux)

java - 使用 cygwin 进行 java 开发有什么问题?

linux - 如何执行使用 for 循环列出的目录列表的操作?

linux - 如何在 Linux 上按名称而不是 PID 杀死进程?

linux - 为什么用(ps -f&)显示进程信息,然后显示1的PPID而不是主shell(-bash)的PID?

linux - 有没有办法通过 shell 脚本上的 SFTP 下载与模式匹配的文件?

awk - 如何在 Awk 中使用单个正则表达式提取多个字符串

linux - 如何使用新名称制作文件的副本,并在文件名中包含原始文件的时间戳?

c - 为什么这四个并行线程在CPU上的负载不相等