読者です 読者をやめる 読者になる 読者になる

Perlメモ(1)

perl

最近、久しぶりにPerlを使ってみたが、UTF-8のデータの扱いで決定版みたいなのがネットではわからなかったので、いろいろと調べたことをメモしておく。PerlでのUTF-8のデータの処理のイメージとしては、Javaとかに近く、内部表現は、Unicodeで管理しているっぽい。Perl的には、UTF-8フラグとか言ってて、それが話をややこししくしている気がする。基本的には、

  1. UTF-8エンコードされたデータを入力する。
  2. Perlプログラムでデコードして、文字として扱える内部表現(Unicodeみたいなもの)に変換して、プログラムを実行する。
  3. 内部表現をUTF-8エンコードして出力する。

というだけなので、難しくない。Javaに近い。

また、実際にコードを書く時には、以下の2つの場合で、書き方を変える。

  1. マシンログのように、永久にASCIIの範囲の文字しか扱わない場合(バイト単位でデータを扱う場合)
  2. 日本語とかも扱う場合(文字単位でデータを扱う場合)

1.の場合、"use utf8;"とかせずに、いつも通りにperlプログラムを書けば良い。

#! /usr/bin/env perl

use strict;
use warnings;

みたいな感じで良いと思う。特に、入出力や正規表現で困ることもない。length関数などの動きも変わらない。ソースは、UTF-8で保存しておくと良い。

2.の場合、I/Oレイヤをutf8で扱って、入出力時に自動的に、decode/encodeしてくれる仕組みにしておくと楽である。

#! /usr/bin/env perl

use utf8;
# perlのIOレイヤーで自動的に標準入出力(STDIN、STDOUT、STDERR)をutf8対応にする。
# open時に自動で、decodeする。
# print時に自動で、encodeする。
use open qw(:std :utf8);

use strict;
use warnings;

# utf8のバイト単位ではなく、文字単位で処理する。
while ( <> ) {
  chomp;
  print "$_\n";
  print length($_), "\n";
}

open(my $fhi, "<", "text.txt") or die $!;
open(my $fho, ">", "out.txt") or die $!;
# 以下で直接指定しても良い。
#open(my $fh, "<:utf8", "text.txt") or die $!;
while ( <$fhi> ) {
  chomp;
  print $fho "$_\n";
  print $fho length($_), "\n";
}

としておけば、標準入出力時もファイル入出力時もdecode/encodeを気にしなくて良い。IO::Fileを使っていても、以下のようにすれば良い。

my $fhi = IO::File->new($path, "<:utf8") or die $!;
my $fho = IO::File->new($path, ">:utf8") or die $!;

UTF-8のデータをPerlの内部表現に正しく変換できれば、日本語で書かれたデータであってもきちんと扱うことができる。

広告を非表示にする