CSVファイルはいろいろ亜種がありますが、こういうのを想定します。
- 文字コードはUTF-8
- 改行はLF
- カラムはダブルクォーテーションで囲んでも囲まなくてもよい
- ダブルクォーテーションで囲んである中に改行を入れることができる
- ダブルクォーテーションの中にダブルクォーテーションを入れるときは、ダブルクォーテーションを2回重ねることでエスケープする("a""b"は「a"b」の意味になる)
このルールをFlexで実装しました。
ルール部分はたった8行なので、お手軽だと思うのですがいかがでしょうか。
csv_parser.l
%option noyywrap nounput noinput nodefault
%x quoted
%{
#include <stdio.h>
int row = 0, col = 0;
%}
%%
\" BEGIN(quoted);
, col++;
\n col=0; row++;
[^,\n"]+ printf("[%d,%d] %s\n", row, col, yytext);
<quoted>{
([^"]|\"\")+ printf("[%d,%d] %s\n", row, col, yytext);
\" BEGIN(INITIAL);
}
%%
int main()
{
yylex();
return 0;
}
入力としてこんなファイルを渡すと
aa,bb,
cc
"dd","ee","ff"
"gg
gg","hh""hh",,
i
こんな出力になります。
[0,0] aa
[0,1] bb
[1,0] cc
[2,0] dd
[2,1] ee
[2,2] ff
[3,0] gg
gg
[3,1] hh""hh
[5,0] i
よく見ると、""を"に置き換える処理が必要そうですが、大体あってそう?
作成にあたっては、こちらのリファレンスを参考にしました。