ルモーリン
ホーム 更新 Perl Sample ランドナー サービス 雑談 コースガイド 鉄ゲタ 自転車 Linux リンク 連絡先

改行をCR(0x0d)で出力

2019-04-17

きっかけは自分のツイート

出来合いの方法が見つからない

2019-04-17 出来合いの方法が見つかりました。 改行をCR(0x0d)で出力2 - Perl - ルモーリン

CRで出力する方法が上手いこと見つけられませんでした(泣)。 関連するページはこの辺り。
Perlの組み込み関数 open の翻訳 - perldoc.jp
open - 入出力のためのデフォルトの PerlIO 層をセットするための perl プラグマ - perldoc.jp
Perlの組み込み変数 $\ の翻訳 - perldoc.jp

openで指定できるオプションを自家製できる

どのご家庭でもよくやるopenの「:utf8」みたいなオプションを自分で作ることができる。 このオプションをなんて呼べば良いのだろう?
PerlIO::via - Helper class for PerlIO layers implemented in perl - metacpan.org

自家製オプション

出力の際に「\n」を「\015(CR)」に置き換えるオプションを自作しました。 ファイル名はMyCR.pmです。 2019-04-17 全て小文字のパッケージ名は予約されているので大文字を入れました。
package MyCR;

use utf8;
use strict;
use warnings;

sub PUSHED {
	my ($class, $mode, $fh) = @_;
	my $dummy = "";

	return bless \$dummy, $class;
}

sub WRITE {
	my ($obj, $buf, $fh) = @_;
	$buf =~ s/\n/\015/g;
	print $fh $buf;
	return length unpack "a*", $buf;
}

1;

使用例

openのオプションに「:via(MyCR)」と指定すると上記で作ったMyCR.pmが使われます。 MyCR.pmをスクリプトと同じディレクトリからロードできるように$FindBin::Binを追加します。
#!/usr/bin/env perl -w

use strict;
use warnings;
use utf8;

use feature "say";

use Encode::Argv;
use Encode::Locale;

use FindBin;
use lib $FindBin::Bin;

use MyCR;

use open IO => ":utf8";

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

$| = 1;

use constant BASENAME => "sample_89";

say "LFで改行";
if (open my $fh, "> :raw :utf8", BASENAME . "_lf.txt") {
	print $fh "たこルカは俺の嫁\n";
	close $fh;
}

say "CRLFで改行";
if (open my $fh, "> :crlf :utf8", BASENAME . "_crlf.txt") {
	print $fh "たこルカは俺の嫁\n";
	close $fh;
}

say "CRで改行";
if (open my $fh, "> :via(MyCR) :utf8", BASENAME . "_cr.txt") {
	print $fh "たこルカは俺の嫁\n";
	close $fh;
}

実行結果

できたファイルをダンプしてみました。 使うツールは違いますがWindowsも同じ内容です。
hexdump -e '"%04_ax " 16/1 "%02x " "\n"' sample_89_crlf.txt
0000 e3 81 9f e3 81 93 e3 83 ab e3 82 ab e3 81 af e4
0010 bf ba e3 81 ae e5 ab 81 0d 0a

hexdump -e '"%04_ax " 16/1 "%02x " "\n"' sample_89_lf.txt
0000 e3 81 9f e3 81 93 e3 83 ab e3 82 ab e3 81 af e4
0010 bf ba e3 81 ae e5 ab 81 0a

hexdump -e '"%04_ax " 16/1 "%02x " "\n"' sample_89_cr.txt
0000 e3 81 9f e3 81 93 e3 83 ab e3 82 ab e3 81 af e4
0010 bf ba e3 81 ae e5 ab 81 0d