PerlでCSVファイルの入出力(Text::CSV_XSの利用)
- Wed
- 23:44
- perl
PerlのCSV入出力のサンプル。
split(/,/)や、単純に,で連結してる例もありますが、実はややこしいCSV。
バイナリデータ、ダブルクォートのエスケープ("は""とする)、カンマ(,)を含むフィールドの取り扱い(,を含む場合はフィールドを"で囲む)など自作するとハマることが多々あるので「Text::CSV_XS」を使うのが簡単で正確です。
Text::CSV_XS (CPAN)
と、いうことでサンプルの作成。
csv.pl
in.csv
実行結果
やってることは、CSVファイル(in.csv)を入力して、行番号を追加したCSVファイル(ot.csv)を出力してるだけです。
バイナリ(コントロールコード)、"および,のエスケープも問題なく行われています。
CSVファイルを扱うコツとしては、各フィールドはかならずダブルクォート(")で囲むようにすることです。
ちなみに、Data::Dumperはオブジェクトをダンプして表示するのに便利です。
split(/,/)や、単純に,で連結してる例もありますが、実はややこしいCSV。
バイナリデータ、ダブルクォートのエスケープ("は""とする)、カンマ(,)を含むフィールドの取り扱い(,を含む場合はフィールドを"で囲む)など自作するとハマることが多々あるので「Text::CSV_XS」を使うのが簡単で正確です。
Text::CSV_XS (CPAN)
と、いうことでサンプルの作成。
csv.pl
01: 02: 03: 04: 05: 06: 07: 08: 09: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: | #!/usr/local/bin/perl use FileHandle; use Data::Dumper; use Text::CSV_XS; my $prm_in_file = $ARGV[0]; my $prm_ot_file = $ARGV[1]; open ($fp_in, $prm_in_file) or die "$!"; open ($fp_ot, "> $prm_ot_file") or die "$!"; my $csv = Text::CSV_XS->new({ 'quote_char' => '"', 'escape_char' => '"', 'always_quote' => 1, 'binary' => 1, }); my $line_cnt = 0; while(<$fp_in>) { $line_cnt++; $status = $csv->parse($_); my @cols_in = $csv->fields(); print "\n---- $line_cnt: IN\n"; print Dumper @cols_in; # add line No. @cols_ot = ($line_cnt, @cols_in); print "---- $line_cnt: OT\n"; print Dumper @cols_ot; $csv->combine(@cols_ot); print $fp_ot $csv->string()."\n"; } close($fp_in); close($fp_ot); |
in.csv
"ABC","123","check,comma","check""w-quote","ctrl^Khat-K" "ABC","123","check,comma","check""w-quote","ctrl^C^D^Ehat-CDE"^K(垂直タブ)、^C、^D、^E はコントロールコードです。catすると下記になります。
$ less in.csv "ABC","123","check,comma","check""w-quote","ctrl^Khat-K" "ABC","123","check,comma","check""w-quote","ctrl^C^D^Ehat-CDE" $ cat in.csv "ABC","123","check,comma","check""w-quote","ctrl hat-K" "ABC","123","check,comma","check""w-quote","ctrlhat-CDE"
実行結果
$ ./csv.pl in.csv ot.csv ---- 1: IN $VAR1 = 'ABC'; $VAR2 = '123'; $VAR3 = 'check,comma'; $VAR4 = 'check"w-quote'; $VAR5 = 'ctrl hat-K'; ---- 1: OT $VAR1 = 1; $VAR2 = 'ABC'; $VAR3 = '123'; $VAR4 = 'check,comma'; $VAR5 = 'check"w-quote'; $VAR6 = 'ctrl hat-K'; ---- 2: IN $VAR1 = 'ABC'; $VAR2 = '123'; $VAR3 = 'check,comma'; $VAR4 = 'check"w-quote'; $VAR5 = 'ctrlhat-CDE'; ---- 2: OT $VAR1 = 2; $VAR2 = 'ABC'; $VAR3 = '123'; $VAR4 = 'check,comma'; $VAR5 = 'check"w-quote'; $VAR6 = 'ctrlhat-CDE'; $ less ot.csv "1","ABC","123","check,comma","check""w-quote","ctrl^Khat-K" "2","ABC","123","check,comma","check""w-quote","ctrl^C^D^Ehat-CDE" $ cat ot.csv "1","ABC","123","check,comma","check""w-quote","ctrl hat-K" "2","ABC","123","check,comma","check""w-quote","ctrlhat-CDE"
やってることは、CSVファイル(in.csv)を入力して、行番号を追加したCSVファイル(ot.csv)を出力してるだけです。
バイナリ(コントロールコード)、"および,のエスケープも問題なく行われています。
CSVファイルを扱うコツとしては、各フィールドはかならずダブルクォート(")で囲むようにすることです。
ちなみに、Data::Dumperはオブジェクトをダンプして表示するのに便利です。