当分隔符是列值的一部分时,计算Unix中文件的列数

时间:2018-10-09 18:09:34

标签: csv unix awk count separator

我在文件中包含以下行:

~Test1~, ~Test2~,,,, ~Test3, Test4~, ~Test5~

这应该解释为7列,因为〜Test3和Test4〜之间的逗号是数据,而不是分隔符。

我想在Unix中有一个动态脚本,该脚本将根据字段定界符(在本例中为',')检查列数(7),并忽略在一个列中存在带逗号的文本。分隔符可以在此过程中更换。

我认为sed中的解决方案是将分隔符从逗号更改为分号';'这将使输出: 〜测试1〜; 〜Test2〜;;;;〜Test3,Test4〜; 〜Test5

1 个答案:

答案 0 :(得分:1)

如果您具有一致的csv,但没有空格,则可以将Ed Morton的FPAT approach与GNU awk结合使用:

$ echo '~Test1~,~Test2~,,,,~Test3, Test4~,~Test5~' | 
        gawk -v FPAT='[^,]*|~[^~]+~' '{for (i=1; i<=NF;i++) print i, "<" $i ">"}'
1 <~Test1~>
2 <~Test2~>
3 <>
4 <>
5 <>
6 <~Test3, Test4~>
7 <~Test5~>

对于您的示例,您可以通过实际捕获然后删除空格和逗号来修改该正则表达式以考虑不一致的空格:

$ echo "~Test1~, ~Test2~,,,, ~Test3, Test4~, ~Test5~" | 
    gawk -v FPAT="([ ]?~[^~]+~,?)|([^,]*,)" '{for (i=1; i<=NF;i++) {sub(/,$/,"", $i); sub(/^ /,"",$i); print i, "<" $i ">"}}'
1 <~Test1~>
2 <~Test2~>
3 <>
4 <>
5 <>
6 <~Test3, Test4~>
7 <~Test5~>

由于您的示例确实在逗号之间有不一致的间距,因此可以使用Ruby的csv解析器:

$ ruby -e 'require "csv"
         options={:col_sep=>", ", :quote_char=>"~"}
         CSV.parse($<, options){ |r| p r}' <<<  '~Test1~, ~Test2~, , , , ~Test3, Test4~, ~Test5~'
["Test1", "Test2", nil, nil, nil, "Test3, Test4", "Test5"]