ルモーリン
ホーム 更新 Perl Sample サービス 雑談 鉄ゲタ Linux リンク 連絡先

Perlサンプル11 CSVファイルを読み書き

2019-12-19

内容

タイトルの通りです(笑) 特長はプログラムの中でCSVがどのような仕様の形式なのか全く触れずに処理する所にあります。 例えばフィールドの値にダブルクォーテーション、改行を入れる場合の仕様を知っていますか? これらの仕様をきちんと知っていれば構いませんが生半可な知識でプログラムを書くくらいなら書かないで済む方法を探しましょう。

コード

知らない仕様の処理はCPANのモジュール頼みです。
Text::CSV - comma-separated values manipulator (using XS or PurePerl) - metacpan.org
#!/usr/bin/env perl

use v5.26;
use utf8;
use strict;
use warnings;

use Data::Dumper;
use Encode::Locale;
use FindBin;
use Text::CSV qw/ csv /;

use feature "say";
use open IO => ":utf8";

binmode STDIN, ":encoding(console_in)";
binmode STDOUT, ":encoding(console_out)";

$| = 1;

use constant CSV_IN => "perlsample_011_in.csv";
use constant CSV_OUT => "perlsample_011_out.csv";
use constant HEADERS => [qw / 名前 年齢 容姿 所属 /];

filedump("読み込むテキスト", CSV_IN);

my $csv = csv(
	in => CSV_IN,
	headers => HEADERS,
);

say "CSV読み込み";
say "-----";
for my $record (@{$csv}) {
	say "$_ => $record->{$_}" for sort keys %{$record};
	say "-----";
}

say "CSV書き出し";
say "-----";
$\ = "\012";
csv(
	encoding => "utf8",
	headers => HEADERS,
	eol => "\n",
	in => $csv,
	out => CSV_OUT,
);

filedump("書き出したテキスト", CSV_OUT);

sub filedump {
	my ($title, $filename) = @_;

	say $title;
	say "-----";

	open my $fh, "<", $filename or die "can not open file $filename.\n";
	while (<$fh>) {
		chomp;
		say;
	}
	close $fh;
	say "-----";
}
入力するCSVファイルはこちら。
たこルカ, X歳, 可愛い, 俺の嫁
ルカ姐さん, 二十歳, 美人, 俺の嫁

実行結果

読み込むテキスト
-----
たこルカ, X歳, 可愛い, 俺の嫁
ルカ姐さん, 二十歳, 美人, 俺の嫁
-----
CSV読み込み
-----
名前 => たこルカ
容姿 =>  可愛い
年齢 =>  X歳
所属 =>  俺の嫁
-----
名前 => ルカ姐さん
容姿 =>  美人
年齢 =>  二十歳
所属 =>  俺の嫁
-----
CSV書き出し
-----
書き出したテキスト
-----
"名前",年齢,容姿,"所属"
"たこルカ"," X歳"," 可愛い"," 俺の嫁"
"ルカ姐さん"," 二十歳"," 美人"," 俺の嫁"
-----

解説

読み込むCSVファイルにヘッダがなく、プログラム内で扱う際に配列のインデックスでしかフィールドを指定できないのは面倒です。 そこで、フィールドに名前を付けつつ読み込めるよう、ヘッダーを指定します。 フィールドに名前があり、フィールドの指定が名前でできるので、その後の扱いが簡単になります。 書き出しの際にヘッダも出力しています。 ヘッダ名がダブルクォーテーションで囲む物とそうでない物があり、utf8の文字コードに変換した結果で囲むのか決めているようです。 CSVの仕様についてはこちらをご覧ください。
CSVファイルフォーマットの解説:CodeZine(コードジン)