Mac のExcelで作ったCSVを適切にPerlで読むには?

| | トラックバック(0)

カテゴリ:

どっかで、これに関する記事を見た気がするんだけど、思い出せない。今の自分にホットな話題なので、記しておく。車輪の再発明上等。Perl Monger or Perl Mohican の方々のツッコミ歓迎。

MacのExcelでcsvを吐くと改行コードがLF

  • さっと表っぽいものを作るとき、Excel はてっとりばやい
  • Mac の Excel からCSVを吐くと文字コードがShift_JIS
  • さらに改行コードが CR (古いMacのデフォルト)
  • これをPerlから読む( open する)と適切に読めない
  • Mac OS X の改行コードは LF であり、それが見つからないので読み込みの終端に辿りつけない

プログラマーにはMac使ってるひとが多いと思うが、Macの人がExcel使ってCSVに吐き出しをすると、大抵これではまる。

かつての自分はこれでよくはまってた。

OSによって改行コードは違う

  • Linux(そして今のMac)は LF (Line Feed)
  • 古いMac(Mac OS 9 以前)は CR (Carriage Return)
  • Windowsは CR + LF

Perlで読む前にCSVを別の改行コードで保存する?

それでもいいと思うけど、たくさんCSVがある場合、いちいち手作業で変換し保存するのはめんどくさい。

ちなみに、文字コード・改行コードを明示的に指定して保存したい場合は、ミミカキエディットが便利です。

メニューバーをカスタマイズすると、こんなふうに直接的に文字コード・改行コードを変更するUIになります。

screenshot_mimikaki.png

僕はSublime Textを使いはじめるまで、テキストエディタはずっとこの mi でした。

Sublime Textだと文字コードを指定して保存は、UTF-8が前提なので、日本語文字コードに関してはできないにひとしいし、改行コードは指定すら出来ないと思う。

sed とか awk とか使えばいいんじゃない?

それは一理あるけど、僕は sed とか awk とかわからない。

がんばってPerlでopenする?

Perlのopen関数は、OSのデフォルトの区切り文字をファイルの読み込みの際に使う。ダイヤモンド演算子( <$fh> の <> )はファイルハンドルから一行読むものだけど、1行というのは、その区切り文字までのことを指す。

なので、この区切り文字を、一時的に書き換えてやればいい。

local $/ = "\r";
open my $fh, '<:crlf:encoding(Shift_JIS)', $file;
my @lines = <$fh>;
close $fh;

局所的に書き換えるために、 local を使う。

区切り文字は $/ という特殊変数がそれに該当する。

かつてのMacの改行文字(CR)をあらわすのが「 \r (または ¥r )」で、localで$/を一時的に \r に書き換える。

そしてopenする。今回はShint_JISなので、openの際にencodingを指定してやる。さらに、テキストモードで開くために :crlf も書く。

この :crlf は実は自分でもよくわかってない。普段、こんな指定をしなくてもファイルはopenできるのに、なんで書かなきゃいけないの?

普段、プログラムを書くときに

open my $fh, '<:encoding(EUC-JP)', $file;

というのはよく書くけど、:crlf や :bytes は書くことがないし、書かなくても目的は十分に達することができるので、そのあたりはよくわからない。

「バイナリで開く」か「テキストで開くか」を明示的に切り替えるときに使うようで、バイナリで開く場合は、 :bytes と書く。

ずっと、 :crlf があるなら、 :cr や:lf もあるのかと思っていたけど、それはない。:crlf か :bytes の二択。

追記:あれー、なんか :crlf を消しても普通に動いた。あれー?

まとめ

  • $/ = "\r"
  • :crlf

改行文字が CR のファイルをPerl でopen する場合、上記の2点1点が必ず必要になるみたい。(どちらか片方だけじゃだめ)

これがBest Practice ?

かどうかは僕にはまだわからない。少なくとも、この方法ならできるとしか。

comments powered by Disqus

トラックバック(0)

このブログ記事を参照しているブログ一覧: Mac のExcelで作ったCSVを適切にPerlで読むには?

このブログ記事に対するトラックバックURL: http://nozawashinichi.sakura.ne.jp/MT-4.25/mt-tb.cgi/1228

comments powered by Disqus

このブログ記事について

このページは、Shinichi Nozawaが2014年4月 9日 21:32に書いたブログ記事です。

ひとつ前のブログ記事は「Net::SMTPSを使って SMTP-AUTH」です。

次のブログ記事は「SQLiteのtransactionにおけるimmediateとexclusive」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。