『メールアドレスはネストしたコメントを持つことができるので正規表現で表わすのは不可能である』
というのは本当だろうか。
正規表現のネストが可能かというのは、実際のところは正規表現の定義と実装による。
PerlやRubyだと、これは可能だ。
試しに『f(g(1))』のようなC言語タイプの簡易的な関数呼び出しにマッチする正規表現を書いてみよう。
Perl版
(??{$code})という形で正規表現を再起的に埋め込むことができる。
#!/usr/bin/perl use strict; use warnings; my @samples = ( "f()", "f(g(a))", "f(g(h(123)))", "f(())", "f(g()", "f(g()))", ); my $re; $re = qr/ [a-z]+ \( ( (??{$re}) | [a-z]+ | [0-9]+| ) \) /x; for my $str (@samples){ my $result = $str =~ /^$re$/g ? "Match" : "Not Match"; print "$str : $result\n"; }
実行結果
[mikeda@test01 work]$ perl func_match.pl f() : Match f(g(a)) : Match f(g(h(123))) : Match f(()) : Not Match f(g() : Not Match
Perl5.10からは別の書き方もできるというウワサも。また調査してみる。
Ruby版
Rubyでも同じ書き方ができる(はず。未確認)が今回は1.9から採用された正規表現ライブラリ、鬼車の機能を使ってみよう。
鬼車では(?
#!/usr/local/bin/ruby samples = [ "f()", "f(g(a))", "f(g(h(123)))", "f(())", "f(g()", ] re = /\A (?<func> [a-z]+ \( (\g<func> | [a-z]+ | [0-9]+ |) \) ) \z/x samples.each do |str| result = re.match(str) ? "Match" : "Not Match" puts "#{str} : #{result}" end
この機能は1.9以降でなければ使えない。
[mikeda@test01 ruby]$ ruby -v ruby 1.9.2p180 (2011-02-18 revision 30909) [x86_64-linux]
実行結果
[mikeda@test01 work]$ ruby func_match.rb f() : Match f(g(a)) : Match f(g(h(123))) : Match f(()) : Not Match f(g() : Not Match
これらがわかりやすいかどうかは別として、枯れていると思われがちな正規表現もまだまだ進化を繰り返しています。
正規表現、奥深ス