【问题标题】:Use awk to fix CSV file with commas in unenclosed fields使用 awk 修复未封闭字段中带有逗号的 CSV 文件
【发布时间】:2013-01-28 12:18:55
【问题描述】:

我有一个 CSV 文件,如下所示:

  height,  comment, name
  152,  he was late, for example, on Tuesday, Fred
  162, , Sam

我无法解析此文件,因为它在注释字段中包含可变数量的未括起来的逗号(但没有其他字段)。我想使用awk(这对我来说很新)修复文件,以便第二个字段中的逗号变为分号:

  height,  comment, name
  152,  he was late; for example; on Tuesday, Fred
  162, , Sam

(将整个字段括在引号中并不能解决我的问题,因为我的 CSV 解析器不理解引号。)

到目前为止,我正在考虑使用 NF 计算未括起来的逗号的数量,然后使用 gsub 将它们替换为令人不快的正则表达式,但我觉得我应该能够利用 awk 来编写更具可读性的程序,但我不是肯定 NF 会这样。

【问题讨论】:

  • Fred后面真的有逗号吗?太丑了,真的有多少个字段?如果文件有随机逗号 other 而不仅仅是嵌入的,那​​么我认为这个问题需要先解决。
  • 如果你能确定额外的逗号每次都在字段2中,如果NF==6,那么你有3个额外的逗号,你可以暂时把第一个和最后一个改成别的,然后将剩余的逗号更改为分号(当然,一次一行)。但是,当然,这确实不是一个灵活的长期解决方案。为什么不使用永远不会出现在数据中的 FS 值导出数据?祝你好运。
  • @DigitalRoss Fred后面没有逗号;那是一个错字。感谢您指出这一点。
  • @shellter 不幸的是,我无法访问原始数据库,因此无法选择不同的 FS。我不太担心它不是一个灵活的解决方案,因为数据是固定的并且不会改变。我会尝试为这个问题添加一个潜在的解决方案。
  • 第一个字段总是一个数字,最后一个字段总是一个单词吗?

标签: macos csv awk


【解决方案1】:

本质上只是一个蛮力解决方案,但相当容易理解。调用

$ awk -F "," -f test.awk test.dat

awk 文件。

$ cat test.awk
{
    printf "%s, ", $1

    if (NF > 3) {
        for (i = 2; i < NF; i++) {
            printf "%s;", $i
        }
        printf ", "
    }
    else {
        printf "%s, ", $2
    }

    printf "%s\n", $NF
}

【讨论】:

  • 这个解决方案的主要问题是它依赖于在每个逗号之后只有一个空白字符,当然可能没有,或者可能有很多并且可能有标签......
  • 谢谢。我选择了您的答案,因为我发现修改超过三列更容易。我知道这不是区分答案的特别好的基础,但是出于任何充分的理由我无法将它们分开。我针对@Ed 描述的问题对其进行了测试,例如输入152,he was late,for example,on Tuesday,Fred,它对我有用,但也许我误解了。无论如何,我的文件在每个逗号后都有空格。
  • @EdMorton:不,这个解决方案根本不依赖空白。它不受制表符、前导空格或尾随空格的影响。
  • 你说得对,我没有注意到你在指示用户在脚本之外使用 -F。为什么不把 BEGIN{FS=","} 放在里面,这样用户就不需要记住添加那个参数了?该脚本当然会在原始数据中添加空格。
  • @Catcall 您提到要修改超过 3 列的脚本。如果您有超过 3 列,那么发布的解决方案都不是一个好的答案,因为它们都假设第一个和最后一个逗号之间的所有逗号都需要转换为分号。您应该发布一个更具代表性的输入集,以便为您的真实数据找到正确的解决方案。
【解决方案2】:
$ cat file
  height,  comment, name
  152,  he was late, for example, on Tuesday, Fred
  162, , Sam

$ awk -v OFS=, '{
   height = comment = name = $0
   sub(/,.*$/,"",height)
   sub(/^.*,/,"",name)
   gsub(/^[^,]+,|,[^,]+$/,"",comment)
   gsub(/,/,";",comment)

   print height, comment, name
}' file
  height,  comment, name
  152,  he was late; for example; on Tuesday, Fred
  162, , Sam

【讨论】:

    猜你喜欢
    • 2017-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-13
    • 2011-05-11
    • 1970-01-01
    • 2012-01-08
    • 2011-05-20
    相关资源
    最近更新 更多