project eulerの8問目を見てて、ふと疑問に思った。
この場合、まず数値列(文字列)から全ての5桁の数字を取ってきたいとする。簡単にするために、20桁の数値列で考える。
$str = '0123456789' x 2; while ($str =~ m/(\d{5})/g) { print $1, "\n"; }
これだと、5桁の数字が
01234 56789 01234 56789
こう出てくるんだけど、そうじゃなくて
01234 12345 23456 34567 45678 56789 ...
ってやるにはどうしたらいいんだろう。
追記 (一応解決した)
pos関数でマッチしたオフセットをシフトさせればいいのかな。
$str = '0123456789' x 2; while ($str =~ m/(\d{5})/g) { print $1, "\n"; pos($str -= 4; }
とやって、マッチする毎にオフセットを4つ前に戻せば望み通りのことはできました。なんだかad hocな感じがするけど :-)
追記2
commentでツッコミいただいたのでsubstrでやってみる。
こんなのでいいですか><
$length = length $str; for $i (0..$length) { $num = substr($str,$i,5); next if $num =~ m/\D/; last if length $num != 5; print "$num\n"; }
追記3
いやいや、こんなことしなくても正規表現で先読みすりゃいいだけじゃないか。
$str = '0123456789' x 2; while ($str =~ m/(?=(\d{5}))/g) { print $1, "\n"; }
先読みでゼロ幅だからマッチ位置は変わらないけど、/gがあるのでループごとに1つ進む。