雑文発散

«前の日記(2008-02-11) 最新 次の日記(2008-02-13)» 編集
過去の日記

2008-02-12 [長年日記]

[PHP][Perl][Ruby] PHP / Perl / Ruby での正規表現の挙動の違い

あるデータが「数字のみの文字列」であるかどうかのチェックに「/^[0-9]+$/」を使っていたところ、行末に「\n」が入っていた場合に、期待通りに動かないというワナにはまった。 具体的には、こんな感じ。

#!/usr/bin/php
<?php
    $str = "1234\n";
 
    if (preg_match('/^[0-9]+$/',$str)) {
        print "ok";
    } else {
        print "ng";
    }
?>

/^[0-9]+$/ は、「0から9の文字だけで構成された1文字以上の文字列」という意味なので、改行コードが入っている文字列 $str は「ng」になってくれそうな気がするのだが、現実は「ok」になる(常識?)

これ、PHP だけがこんな挙動なのかな?と思って、Perl / Ruby も調べてみたが同じ挙動だった。これはこれで正解ってことなんだろう、きっと。

それとは別のところで、PHP / Perl と Ruby とで挙動が違うモノがあったので、ちょっと書いてみる事にする。

まずは PHP のコード。test.php とする。

#!/usr/bin/php
<?php
 
$array = array('1234',
               '1234' . "\n",
               '1234' . "\n" . '5678');
 
for ($i = 0; $i < count($array); ++$i) {
    if (preg_match('/^[0-9]+$/',$array[$i])) {
        print "ok\n";
    } else {
        print "ng\n";
    }
}
?>

次は Perl のコード。test.pl とする。

#!/usr/bin/perl
 
@array = ('1234',
          '1234' . "\n",
          '1234' . "\n" . '5678');
 
for ($i = 0; $i < @array; $i++) {
    if ($array[$i] =~ /^[0-9]+$/) {
        print "ok\n";
    } else {
        print "ng\n";
    }
}

最後は Ruby のコード。test.rb とする。

#!/usr/bin/ruby
 
array = ['1234',
         '1234' + "\n",
         '1224' + "\n" + '5678'];
 
array.each { |tmp|
   if /^[0-9]+$/ =~ tmp then
      print "ok\n"
   else
      print "ng\n"
   end
}

これを実行すると、次のようになる。

$ ./test.php 
ok
ok
ng
$ ./test.pl  
ok
ok
ng
$ ./test.rb
ok
ok
ok

Ruby だけ、最後の "1234\n5678" という文字列も /^[0-9]+$/ でヒットする。PHP / Perl と Ruby のどちらが「正しい」のかは良く分からんけど、直感的には PHP / Perl の方を期待するなぁ。

ちなみに PHP にはいくつかの正規表現系があるのだけど、今回は(オレの趣味で)Perl 互換の正規表現を利用している。なので、Perl と動きが同じになっている(のだと思う)。他の正規表現系は試していない。

テストは Mac OS X Leopard 上で実施した。それぞれの言語系のバージョンは以下の通り。

$ /usr/bin/php --version
PHP 5.2.4 (cli) (built: Sep 23 2007 22:34:35) 
Copyright (c) 1997-2007 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2007 Zend Technologies
 
$ /usr/bin/perl --version
 
This is perl, v5.8.8 built for darwin-thread-multi-2level
(with 1 registered patch, see perl -V for more detail)
 
Copyright 1987-2006, Larry Wall
 
Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.
 
Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.
 
$ /usr/bin/ruby --version
ruby 1.8.6 (2007-09-24 patchlevel 111) [universal-darwin9.0]

[] スター・ウォーズ クローン大戦の公開日が決定したそうだ!

ジャパン スター・ウォーズ ドットコムの情報によると、テレビシリーズとして予定されていた「スター・ウォーズ クローン大戦」のファーストエピソード(第一話ってこと?)が劇場公開される事になったらしい。

北米での公開が今年の8月15日。日本を含む他国での公開日は近日発表との事。3ヶ月遅れくらいかなぁ。。。

本日のツッコミ(全1件) [ツッコミを入れる]
hnw (2008-02-13 14:53)

こんにちは。/^([0-9]+)$/として$1を見てみると改行が含まれていないのではないかと思います。