改行混じりのcsvをperlで処理する

2014/6/24 [14:00:22] (火) 天気

ASPのデータベースからエクスポートされたcsvの集計作業ということで眺めてたら、セル内で改行がある・セル内にコンマがある、という腐ったデータでムカついた(「csvにエクスポート」するんだからコンマや改行の扱いをちょっと考えてくれりゃいいものを)


あちこちの管理画面でエクスポートというとcsv形式になってることが多い。

それをエクセルに読み込んで…

・行や項目の多いシートになると横スクロールに縦スクロールで大騒ぎ。

・改行が混じってるとその行だけセルが異様に広がっていて目障り。

・csvの値は属性を持ってないのでエクセルが勝手に判断してただの数値を日付表示にしたり意味不明の表示になっていることなどざらにあってイライラさせられる。


こういうデータをエクセル上で手作業すると簡単に間違う。わたしは。


なもんで、perlで読み込んで一括処理・集計した方が早いし確実。その場限りの使い捨てのスクリプトを書いて対応している…ところが、perlやAWK、sedなどは行単位での処理が基本。改行の混じったcsv、まさに今回のようなcsvデータは扱いが面倒くさい。


ということで今日もまた「Perlメモ」のお世話になりました。


perlでセルに改行やコンマが入っているcsvデータを処理する。


while (my $line = <DATA>) {
  $line .= <DATA> while ($line =~ tr/"// % 2 and !eof(DATA));

  $line =~ s/(?:\x0D\x0A|[\x0D\x0A])?$/,/;
  @values = map {/^"(.*)"$/s ? scalar($_ = $1, s/""/"/g, $_) : $_}
                ($line =~ /("[^"]*(?:""[^"]*)*"|[^,]*),/g);
  #これでリストに値が入る
}

(出典:http://www.din.or.jp/~ohzaki/perl.htm

このまま利用させていただきました(ありがとうございます)


今さら知ったこと気づいたこと。

正規表現のパターンマッチは、リストコンテキストで評価すると()でくくった正規表現でひっかかった部分文字列のリストを返す。


$str = ’abcd123efghi543jklmn’;
print $str =~ m!(\d+)!g;

今までこんなケースでは修飾子「g 」は使えないもんだとばかり思っていて 1 while(s/(.+)/$1/) など1つずつパターンマッチさせて処理していた。


scalar関数。リストの要素を数えるぐらいしか使ってなかったんだけど、今回このスクリプトでの使い方がまるでわからず調べてみたところ

http://perldoc.jp/func/scalar

scalar は単項演算子なので、EXPR として括弧でくくったリストを使った場合、 これはスカラカンマ表現として振舞い、最後以外の全ては無効コンテキストとして 扱われ、最後の要素をスカラコンテキストとして扱った結果が返されます。

ここでは「””」を「”」にするために使っている。

mapの条件式で部分文字列が「”」で括られていたら、scalar関数に文字列を渡して

「部分文字列をscalar関数のデフォルトに入れて、「””」を「”」に置換して、デフォルトの$_を返す」

左から順番に評価していって、コンマで繋いで各々の結果を切り捨てて、最後に残った式の結果を返すためだけにscalar関数を使っている。トリッキーで面白いなあ。これはループの中で使い途がある。


勉強になりました。



「perlパズル」

↑以前書いた、コンマの使い方のメモ


初めてのPerl 第6版

『初めてのPerl 第6版』

ランダル・L.シュワルツ

<<2026/1>>
    123
45678910
11121314151617
18192021222324
25262728293031
検索:

【最近の20件】