PerlでCSVファイルの入出力(Text::CSV_XSの利用)

PerlのCSV入出力のサンプル。
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はオブジェクトをダンプして表示するのに便利です。

関連記事

Comment

(編集・削除用)
管理者にだけ表示を許可

Trackback

URL
https://nosource.blog.fc2.com/tb.php/119-264e2675
この記事にトラックバック(FC2Blog User)

カテゴリ

Amazon

アクセスランキング

[ジャンルランキング]
コンピュータ
249位
アクセスランキングを見る>>

[サブジャンルランキング]
プログラミング
38位
アクセスランキングを見る>>

RSSリンクの表示

ブロとも申請フォーム

Copyright © nopgm