【问题标题】:format arbitrary data in CSV以 CSV 格式格式化任意数据
【发布时间】:2021-09-18 07:21:16
【问题描述】:

我有一个任意格式的文件:

Name:pod1
Image:image1
cpu:2
memory:1000Mi
cpu:300m
memory:1000Mi
Name:pod2
Image:image2
cpu:2
memory:1000Mi
cpu:300m
memory:1000Mi

它实际上是 Kubernetes 集群中的 pod 列表。

我需要像这样转换 csv 中的数据:

Name,Image,cpu,memory
pod1,image1,2,1000Mi
pod1,image1,300m,1000Mi
pod2,image2,2,1000Mi
pod2,image2,300m,1000Mi

第 2 行和第 4 行的前 2 个值重复第 1 行和第 3 行的前 2 个值。

我最好在 bash 中有一个结合 grep/sed/awk 的解决方案,但那是我很挑剔。我对 Python 甚至 Powershell 中的任何解决方案都非常满意。

非常感谢!

【问题讨论】:

  • 所有字段是否始终存在,是否保留顺序?
  • 到目前为止您尝试过什么(代码)?标签是否总是NameImagecpumemory
  • @Raphael - 是的,总是按这个顺序

标签: python bash csv kubernetes formatting


【解决方案1】:

假设顺序是固定的:当我看到“内存”行时,我会打印完整的记录。

awk '
    BEGIN {FS = ":"; OFS = ","; print "Name","Image","cpu","memory"}
    {record[$1] = $2}
    $1 == "memory" {print record["Name"], record["Image"], record["cpu"], record["memory"]}
' file

【讨论】:

    【解决方案2】:

    一个通用但基于 python 的解决方案:

    from pandas import DataFrame
    
    text = """Name:pod1
    Image:image1
    cpu:2
    memory:1000Mi
    cpu:300m
    memory:1000Mi
    Name:pod2
    Image:image2
    cpu:2
    memory:1000Mi
    cpu:300m
    memory:1000Mi"""
    
    lines = text.splitlines(keepends=False)
    record = dict()
    records = list()
    for line_number, line in enumerate(lines):
        field, value = line.split(':')
        if field in record:
            # we have seen this field before thus this record is complete
            # and the field value pair belongs to the next record
            records.append(record)
            # create a new empty record
            record = dict()
        # set the value for the current record
        record[field] = value
    
    dataframe = DataFrame(records)
    dataframe.to_csv('here_we_go.csv', index=False)
    

    注意:此解决方案也适用于缺失或无序的字段,但两者结合可能会破坏它。

    【讨论】:

    • “我们之前看过这个字段,所以这个记录是完整的”——这很聪明。
    • 问题:这会发出 CSV 标题行吗?
    • @glennjackman 是的(这是由熊猫处理的)
    【解决方案3】:

    由于顺序始终一致,只要看到memory 键就可以写入一行:

    import csv
    
    with open('input.txt', newline='') as f_input, open('output.csv', 'w', newline='') as f_output:
        csv_output = csv.DictWriter(f_output, fieldnames=['Name', 'Image', 'cpu', 'memory'])
        csv_output.writeheader()
        block = {}
        
        for row in csv.reader(f_input, delimiter=':'):
            if len(row) == 2:   # skip blank lines
                block[row[0]] = row[1]
            
                if row[0] == 'memory':
                    csv_output.writerow(block)
    

    给予:

    Name,Image,cpu,memory
    pod1,image1,2,1000Mi
    pod1,image1,300m,1000Mi
    pod2,image2,2,1000Mi
    pod2,image2,300m,1000Mi
    

    【讨论】:

      猜你喜欢
      • 2015-12-18
      • 1970-01-01
      • 2017-10-01
      • 2014-03-04
      • 2012-03-05
      • 2016-04-27
      • 2012-11-15
      • 2015-07-22
      • 2020-10-23
      相关资源
      最近更新 更多