PerlでCSVのダブルクォテーションで囲まれた部分のカンマを削除しよう
CSV(カンマ区切りのテキスト)なデータを処理するときに、何が厄介かって "(ダブルクォート)で囲まれたフィールドの中に存在する ,(カンマ)だったりします。例えばこんな感じ(↓)のヤツです。
日本,"9,222.52",2012/11/21
アメリカ,"12,836.89",2012/11/22
だったら、そのカンマを取り除いてしまえ! というわけで、プログラムを書いてみました。
#!/usr/bin/perl use strict; use warnings; my $qw = '"'; # 引用符を定義 my $dlm = ","; # 区切り文字を定義 open(RH, "<", "from.csv"); open(WH, ">", "to.csv"); while(<RH>){ print WH RemoveDelimiterInQuotes($_, $qw, $dlm); } close(WH); close(RH); exit; sub RemoveDelimiterInQuotes { my $str = shift; # 対象文字列 my $qw = shift; # 引用符 my $dlm = shift; # 区切り文字 my @substrs = ( $str =~ /$qw[^$qw]*$qw/g); for my $substr (@substrs){ my $target = $substr; $substr =~ s/$dlm//g; $str =~ s/\Q$target\E/$substr/; } return $str; }
from.csv を読み込んでダブルクォートに囲まれた部分のカンマを削除して、to.csv に書き出します。これでバッチリだね!
と、ここまで出来てから、な~んとなくもう一度 Web で検索してみたところ、標準モジュールの Text::ParseWords を使えばもっと簡単に出来たことが判明。あちゃ~。
perlでcsvファイルを読む(ダブルコーテーション内カンマを無視したい) | PerlのQ&A【OKWave】
折角なので Text::ParseWords を使って書き直したのがこちらになります。
#!/usr/bin/perl use strict; use warnings; use Text::ParseWords; my $dlm = ","; # 区切り文字を定義 open(RH, "<", "from.csv"); open(WH, ">", "to.csv"); while(<RH>){ chomp; my @parsed = parse_line($dlm, 1, $_); for(my $i=0; $i<=$#parsed; $i++){ $parsed[$i] =~ s/$dlm//g; } print WH join($dlm, @parsed)."\n"; } close(WH); close(RH); exit;
今回は処理内容を同じにするために、あえて to.csv として書き出していますが、parse_line を通した時点でデータはフィールドごとに分かれていますので、そのまま目的の処理をしてしまうのが正しい使い方でしょうね。
大変助かりました。ありがとうございます
Posted by: ct | 04/16/2015 at 15:25
コメントありがとうございます。
お役に立ててなによりです。
Posted by: 夢界 | 04/16/2015 at 16:17