使用sed清理CSV文件

时间:2014-03-28 14:35:42

标签: regex bash unix csv sed

首先,我想说我已经详尽地搜索了这个解决方案。重要的是我使用sed或至少混合使用* nix命令行实用程序来解决此问题。在某些情况下,我正在处理格式错误的CSV文件,但我很确定它是可解决的。我只缺少一块拼图。

我想建立一个从CSV到管道的转换器。它应该解决以下问题:

  1. 删除","并替换为|
  2. 删除",并替换为|
  3. 删除,"并替换为|
  4. 在引号内删除引号 例如:dog,"john "bud" smith",cat(变为dog|john bud smith|cat
  5. 删除不在引号之间的,并替换为|
  6. 我用sed命令完成了几乎所有这些操作,但是我对字段中的逗号感到难过。可能有更好的方法,但我对这个主题没有创造性的想法。一个正确的解决方案将解析此字符串:

    1234,"bill","butler","1000,p"r"airie",1234,6789
    

    1234|bill|butler|1000,prairie|1234|6789
    

    这是我到目前为止所做的:

    echo '1234,"bill","butler","1000,p"r"airie",1234,6789' |
    sed -e 's/","/|/g' -e 's/,"/|/g' -e 's/",/|/g' -e 's/"//g'
    

3 个答案:

答案 0 :(得分:2)

您可以使用perlText::Parsewords救援:

perl -MText::ParseWords -nle 'print join "|", map {s/"//g; $_} parse_line(",",1,$_);' file

对于您的样本输入,它会产生:

1234|bill|butler|1000,prairie|1234|6789

答案 1 :(得分:0)

echo '1234,"bill","butler","1000,p"r"airie",1234,6789' | 
sed -e 's/\([0-9"]\),\([0-9"]\)/\1|\2/g' -e 's/"//g'

我定义了一条规则:

, is transformed to the | if it is between numbers or quotes

以后再删除所有引号

EDIT1 看起来我的解决方案无效,但此问题有nice thread

答案 2 :(得分:0)

#!/bin/bash                                                                                                                                                                                      

l='1234,"bill","butler","1000,p"r"airie",1234,6789'

has_quote_in_quote()
{
    echo $1 | grep -q '[^,]"[^,]'
}

clean_quote_in_quote ()
{
    echo $1 | sed -E -e 's/([^,])"([^,])/\1\2/g'
}

parse()
{
    echo $1 |grep -E -o  '[^"]*|"[^"]*"'
}

pipe_unquoted_commas()
{
    for f in $(parse $1); do echo $f|sed -E -e '/^[^"]/s/,/|/g'; done
}

while has_quote_in_quote $l; do b=$(clean_quote_in_quote $l); l=$b; done

echo $(printf "%s" $(pipe_unquoted_commas $b|sed 's/"//g'))

运行此产生

1234|bill|butler|1000,prairie|1234|6789

对我而言,这不是你想要的,但让我解释它是如何运作的。

has_quote_in_quote找到任何与逗号不相邻的'“'。clean_quote_in_quote删除它可以找到的所有内容,但是如果它们真的很接近,则需要多次传递,因为在这种情况下sed已超过单引号字符 - 无论是偶然的还是刻意的,你的例子都是精心挑选的。解析选择一个不带引号或引用的文本段,包括引号。在while循环中删除“引用的引号”然后转换逗号在最后一行中,删除了引号字符。

// P