1

通常,我会做类似的事情

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

任何提示将不胜感激。否则,我可能会改用另一种语言来处理这些东西。

4

3 回答 3

2

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

未来可能出现的问题是:

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

我通常倾向于遵循这样的理念,即如果有一个(信誉良好的)模块可以解析您必须解析的某些格式,请使用它而不是制作自制软件

我不认为 bash 有这样的东西,但Perl有一些。我会去Text::CSV_XS。用 CI 编写期望它会非常快。

于 2012-12-23T05:30:42.860 回答
1

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

查找输入文件中从未出现过的字符。使用 C 程序解析 CSV 文件并将行打印到具有不同分隔符的标准输出。编写该程序留作练习,但我确信那里有 CSV 解析 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建议使用行尾标记而不是整行。

另一个小问题:您的问题代码中有一个“无用的使用cat。你可以替换这个:

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

这样:

while read LINE
do
     ...
done < $FILENAME

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

于 2012-12-23T05:29:38.720 回答
1

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

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

或在每一行:

line=$(echo $line | sed 's/\("[^,"]*\),\([^"]*"\)/\1;\2/g')
于 2012-12-23T05:30:30.577 回答