- ベストアンサー
マッチングしたい要素同士が文字列の中で重なっている場合
perlの正規表現マッチングでうまくいかないことがあり、質問させていただきたいと思います。 たとえば AAAAAAXBBBXCCX という文字列があって「各Xの左側に位置する6文字をすべてあつめる」ということをしたいと思っています。 この文字列では AAAAAA AAXBBB BBBXCC が自分の取り出したい文字になります。 そこで以下のようなコードを書いたのですが my $seq = "AAAAAAXBBBXCCX"; my $length = 6; my @fragmentlist ; @fragmentlist = $seq =~ /(.{$length})X/g ; foreach my $fragment (@fragmentlist ){ print $fragment , "\n"; } 実際に出力されるのは AAAAAA BBBXCC となり、 AAXBBB は認識されないようです。これはおそらくAAAAAAとAAXBBBが元の文字列の中で部分的に重なっているからだと思います。 このようなマッチング対象が文字列の中で重なっている場合は、どのようにすればすべてのパターンを集めることができるでしょうか? active perl 5.8.8 , WinXP sp2環境です。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
my $seq = "AAAAAAXBBBXCCX"; my $length = 6; my @fragmentlist ; @fragmentlist = $seq =~ /(?<=(.{$length}))X/g ;###変えた foreach my $fragment (@fragmentlist ){ print $fragment , "\n"; } これでどうですか? Xをマッチさせて,それから6文字を戻り読みさせて 戻った分をキャプチャしています. /gなので,Xを順番にマッチします. ただし,Xよりも左に6文字ないときはマッチしません. 戻り読みは固定文字数分しか指定できないという制限があるので そういう場合は何か細工が必要でしょう. Perl5.10だと,\Kとかで 「something like floating length positive lookbehind.」 だそうですが,実験してないのでよく分かってません(^-^;; Perl5.8でもRegexp::Keepを使えば\Kは使えるとのことです.
その他の回答 (1)
- kapura
- ベストアンサー率50% (48/95)
単純に$seqからXを探して、そこから$lengthと1 (Xの長さ) だけ戻って、$length分の文字列を@fragmentlistに取得したら、どうでしょうか。 my $seq = "AAAAAAXBBBXCCX"; my $length = 6; my @fragmentlist; while ($seq =~ /X/g) { my $idx = pos($seq) - $length - 1; push @fragmentlist, substr($seq, $idx, $length) if $idx >= 0; } foreach my $fragment (@fragmentlist) { print $fragment , "\n"; }
お礼
なるほど、考え方を少し変えてみてもいいんですね。 勉強になりました。 どうもありがとうございました。
お礼
読み戻りですか、この方法は知りませんでした。 こちらでも試して、うまくいきました。 どうもありがとうございました。