/gcと\Gを使って複数の正規表現式でトークンを少しずつ削りとる

複数の正規表現式で文字列からトークンを切り出したいことがある。しかし、以下のコードは動かない。無限ループになってしまう。

#!perl -w
# THIS DOES NOT WORK!!!
use 5.10.0;
use strict;
use utf8;

my $s = 'foo bar baz FOO BAR BAZ';

while( 1 ) {
    if( $s =~ /\b (f..) \b/xmsig) { # first matching expression
        say $1;
    }
    elsif( $s =~ /\b (b..) \b/xmsig) { # second matching expression
        say $1;
    }
    else {
        die 'finished';
    }
}

これは[twitter:@akajiro]さんと[twitter:@hio]さんに教えてもらった結果、解決した。つまり、正規表現修飾子/cと、前回のマッチ位置を意味するメタ文字\Gを使えばいい。動作するコードは以下のようになる。

#!perl -w
use 5.10.0;
use strict;
use utf8;

my $s = 'foo bar baz FOO BAR BAZ';

while( 1 ) {
    if( $s =~ /\G \s* \b (f..) \b/xmsigc) { # first matching expression
        say $1;
    }
    elsif( $s =~ /\G \s* \b (b..) \b/xmsigc) { # second matching expression
        say $1;
    }
    else {
        die 'finished';
    }
}

空白を読み飛ばすための\s*をいれているほかは特に工夫はない。
参考文献: perlre