「perlに関する玄人向けTIPS集」へのツッコミ

perlに関する玄人向けTIPS集【1】 をみたら、あまりにツッコミどころが満載だったのでちょっと書いておきます。気を悪くされたらごめんなさい(何か変な日本語だ)。

ハッシュのキーをABC順にソートする

foreach my $key(sort $hash{$a} cmp $hash{$b} keys %hash){

sort の引数は

    sort SUBNAME LIST
    sort BLOCK LIST
    sort LIST

なので、 sort {} @array が正しい。しかも、{ $hash{$a} cmp $hash{$b} } は hash の value での sort ですね。正しくは以下のようになるのかと。

#!/usr/local/bin/perl

my %hash = (
    c => 'mount',
    m => 'play',
    a => 'zip',
    l => 'view',
    e => 'remove',
);

for my $key ( sort { $a cmp $b } keys %hash ) {
    warn "$key : $hash{$key}\n";
    # $key,$value に何らかの処理。
}

文字を全角半角含めて1文字づつ処理する

my $s = "あいうえお1文字づつ処理デキルYO";

my $c;
while ( $s =~ /([\x20-\x7F]|\x8E[\xA1-\xDF]|[\xA1-\xFE][\xA1-\xFE])/g ) {
## 何らかの処理
# printf "%02d:%s\n",$c++,$&);
printf "%02d:%s\n", $c++, $&;
}

えーっと、まず typo。あと、「なんらかの処理」の後に $& を参照すると、$& が「なんらかの処理」中に他のマッチングで変更されてしまう可能性があるのでお薦めできません。$& を使用する事自体正規表現のパフォーマンスを激しく落とす行為なのでなるべくなら使わない方がよいのかと(perldoc perlvar 見てください)。
そもそも文字列が utf8 だったら正規表現使わなくっても split で出来る。

#!/usr/local/bin/perl

use Encode;

my $euc_str  = "数字1234アルファベットabcde";
my $utf8_str = decode( 'euc-jp', $euc_str );

binmode STDOUT, ':utf8';
my $i;
for my $s ( split //, $utf8_str ) {
    printf "%02d:%s\n", ++$i, $s;
}

定数を宣言する use constant

use constant YYY => [100, 200, 300];
...
print YYY->[1], "\n";

最近の Perl のコンスタントは複数の宣言を一回の use で書けます。あと、無名の配列とかハッシュとかをコンスタントで宣言すると、その中にある変数は読み出し専用ではなくなってしまうので、意図した動作をしない可能性があります。人に勧めるなら constant よりは Readonly のほうがいいような気がします。

#!/usr/local/bin/perl

use constant {
    SEC   => 0,
    MIN   => 1,
    HOUR  => 2,
    MDAY  => 3,
    MON   => 4,
    YEAR  => 5,
    WDAY  => 6,
    YDAY  => 7,
    ISDST => 8,
};
print HOUR, "\n";

use constant YYY => [100, 200, 300];

print YYY->[0], "\n";
YYY->[0] = 0;
print YYY->[0], "\n";

"%ほげほげ%"を sprintf printf で出力。

printf("\%%%s\%","ほげほげ")

printf "%%%s%%\n", "ほげほげ";

でいいんじゃないの?
perldoc -f sprintf

    %%   a percent sign

って書いてあるし。

[Jcode] 文字コード変換

require "jcode.pl" がカッコワルイなら、use Jcode もカッコワルイんじゃないかな。ここは素直に Encode.pm 使いましょう。

文字列の文字コードを調べる

unpack "H*", $str;