Perl 将嵌入逗号的CSV文件按行高效地转换为bash数组
通常,我会做类似的事情Perl 将嵌入逗号的CSV文件按行高效地转换为bash数组,perl,bash,shell,Perl,Bash,Shell,通常,我会做类似的事情 IFS=',' columns=( $LINE ) 其中$LINE是我正在读取的csv文件中的一行 但是,如何处理嵌入逗号的csv文件?我必须处理几百gig的文件,所以所有的事情都需要快速完成,也就是说,没有一行的多次读取,绝对没有循环(上次我试过这样做时,有几个因素降低了速度) 守则的一般结构如下: FILENAME=$1 cat $FILENAME | while read LINE do IFS="," columns=( $LINE )
IFS=','
columns=( $LINE )
其中$LINE是我正在读取的csv文件中的一行
但是,如何处理嵌入逗号的csv文件?我必须处理几百gig的文件,所以所有的事情都需要快速完成,也就是说,没有一行的多次读取,绝对没有循环(上次我试过这样做时,有几个因素降低了速度)
守则的一般结构如下:
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
任何提示都将不胜感激。否则,我可能会转而使用另一种语言来处理这些问题。这不是一个完整的答案,但这是一种可能的方法 查找输入文件中从未出现过的字符。使用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
<代码>换行符表示行结束标记,而不是整行
另一个小问题:你的问题中的代码中有一个错误。您可以替换此:
cat $FILENAME | while read LINE
do
...
done
据此:
while read LINE
do
...
done < $FILENAME
读取行时
做
...
完成<$FILENAME
但是如果你用我建议的假想的C程序代替猫,你仍然需要管道。这不是一个完整的答案,但它是一种可能的方法 查找输入文件中从未出现过的字符。使用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
<代码>换行符表示行结束标记,而不是整行
另一个小问题:你的问题中的代码中有一个错误。您可以替换此:
cat $FILENAME | while read LINE
do
...
done
据此:
while read LINE
do
...
done < $FILENAME
读取行时
做
...
完成<$FILENAME
但是如果你用我建议的假想的C程序替换了猫,你仍然需要管道。你可以使用sed或类似的东西将引号中的逗号转换成其他的序列或标点符号。如果你不在乎引号里的东西,你甚至不需要把它们改回去。您可以对整个文件执行此操作:
sed 's/\("[^,"]*\),\([^"]*"\)/\1;\2/g' input.csv > intermediate.csv
或在每行上:
line=$(echo $line | sed 's/\("[^,"]*\),\([^"]*"\)/\1;\2/g')
您可以使用sed或类似的方法将引号中的逗号转换为其他序列或标点符号。如果你不在乎引号里的东西,你甚至不需要把它们改回去。您可以对整个文件执行此操作:
sed 's/\("[^,"]*\),\([^"]*"\)/\1;\2/g' input.csv > intermediate.csv
或在每行上:
line=$(echo $line | sed 's/\("[^,"]*\),\([^"]*"\)/\1;\2/g')
可能嵌入的逗号只是解析这些CSV文件时遇到的第一个明显问题
未来可能出现的问题有:
- 嵌入的换行符分隔符
- 嵌入式utf8字符
- 对空格,空字段,逗号周围空格,未定义值的特殊处理
- 嵌入的换行符分隔符
- 嵌入式utf8字符
- 对空格,空字段,逗号周围空格,未定义值的特殊处理
我认为bash没有这样的功能,但是对于Perl有一些功能。我会去的。由于是用C语言编写的,我希望它会非常快。谢谢你的猫提示。我不知道。顺便说一句,示例代码替换不起作用@saccharine:Ah,是的,你是对的(我应该在发布之前尝试一下)。引用链接消息:“不允许在复合命令(如while)前面放置重定向。重定向必须始终出现在复合命令的末尾。重定向只能出现在简单命令中的任何位置。”感谢cat提示。我不知道。顺便说一句,示例代码替换不起作用@saccharine:Ah,是的,你是对的(我应该在发布之前尝试一下)。引用链接消息:“不允许在复合命令(如while)前面放置重定向。重定向必须始终出现在复合命令的末尾。重定向只能出现在简单命令中的任何位置。”您能否详细解释sed命令的作用?我不太熟悉使用reg ex,你的顺序让我很困惑。即使打开wiki页面,我也很难解析它。这似乎是最简单的答案,但它增加了一行额外的可读性。我能让它在columns=($LINE)运行的同时运行吗?您能解释一下sed命令的作用吗?我不太熟悉使用reg ex,你的顺序让我很困惑。即使打开wiki页面,我也很难解析它。这似乎是最简单的答案,但它增加了一行额外的可读性。我可以让它在列=($LINE)运行的同时运行吗