将带有嵌入式逗号的CSV文件有效地按行转换为bash数组

时间:2012-12-23 05:06:51

标签: perl bash shell

通常,我会做类似

的事情
IFS=','
columns=( $LINE )

其中$ LINE是我正在阅读的csv文件中的一行。

但是,如何处理带有逗号的csv文件?我必须处理几百个文件,所以一切都需要快速完成,即没有多行读数,绝对没有循环(上次我尝试减慢了几个因素)。

代码的一般结构如下

FILENAME=$1
cat $FILENAME | while read LINE
do
    IFS=","
    columns=( $LINE )
    # affect columns changes here
    newline="${columns[*]}"
    echo "$newline"
done

最好,我需要一些东西

FILENAME=$1
cat $FILENAME | while read LINE
do
    IFS=","
    # code to tell bash to ignore if IFS is within an open quote
    columns=( $LINE )
    # affect columns changes here
    newline="${columns[*]}"
    echo "$newline"
done

任何提示将不胜感激。否则,我可能会转而使用另一种语言来处理这些事情。

3 个答案:

答案 0 :(得分:2)

可能嵌入式逗号只是您在解析这些CSV文件时遇到的第一个明显问题。

可能出现的未来问题是:

  • 嵌入式换行分隔符
  • 嵌入式utf8字符
  • 空白空白字段逗号空格 undef值
  • 的特殊处理

我通常倾向于遵循的理念如果有一个(信誉良好的)模块解析一些 您需要解析的格式,使用它而不是制作自制

我认为bash没有这样的东西,但有一些 Perl 。我会去Text::CSV_XS。用C语写,我希望它非常快。

答案 1 :(得分:1)

这不是一个完整的答案,但这是一种可能的方法。

查找输入文件中从不出现的字符。使用解析CSV文件的C程序,并使用不同的分隔符将行打印到标准输出。编写该程序是一个练习,但我确信那里有解析C语言的源代码。将C程序的输出传送到您的脚本中。

例如:

FILENAME=$1
new_c_program $FILENAME | while read LINE
do
    IFS="|"
    # code to tell bash to ignore if IFS is within an open quote
    columns=( $LINE )
    # affect columns changes here
    newline="${columns[*]}"
    echo "$newline"
done

一个小问题:我选择$newline以外的名字; newline建议使用行尾标记而不是整行。

另一个小问题:您的问题代码中有"Useless Use Of cat"。你可以替换它:

cat $FILENAME | while read LINE
do
    ...
done

由此:

while read LINE
do
     ...
done < $FILENAME

但如果你用我建议的假设C程序替换cat,你仍然需要管道。

答案 2 :(得分:1)

您可以使用sed或类似的东西将引号内的逗号转换为其他序列或标点符号。如果您不关心引号中的内容,那么您甚至不需要更改它们。您可以在整个文件中执行此操作:

sed 's/\("[^,"]*\),\([^"]*"\)/\1;\2/g' input.csv > intermediate.csv

或在每一行:

line=$(echo $line | sed 's/\("[^,"]*\),\([^"]*"\)/\1;\2/g')