• ベストアンサー

マッチングしたい要素同士が文字列の中で重なっている場合

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環境です。

質問者が選んだベストアンサー

  • ベストアンサー
  • kabaokaba
  • ベストアンサー率51% (724/1416)
回答No.1

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は使えるとのことです.

hydrozoa
質問者

お礼

読み戻りですか、この方法は知りませんでした。 こちらでも試して、うまくいきました。 どうもありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (1)

  • kapura
  • ベストアンサー率50% (48/95)
回答No.2

単純に$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"; }

hydrozoa
質問者

お礼

なるほど、考え方を少し変えてみてもいいんですね。 勉強になりました。 どうもありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • 位置指定の文字マッチングと同時に置換

    active perl v5.8を使用しています。 文字列のマッチングと置換について質問させてください。 たとえば"ABCDEF"という文字列があったとします。この文字列の3文字目の 後に"-"(スペースバー)を入れたいと思います。"ABC-DEF"のように。 この場合文字の種類ではなく、文字の位置から置換する対象を決めること にしたいのです。 正規表現をつかい3文字目を見つけ、3文字目 + "-"に置換すればよいと考えました。 my $seq = "ABCDEF"; $seq =~s/.{2}(.)/$1-/; #3番目の文字を(.)に入れて記憶 としたのですが、こうすると(C-DEF)のように初めのほうの文字が消えてしまいます。(スクリプトを見直してみると当然なのですが。。。) 後方参照という方法で $seq =~s/.\3/$1-/; というふうにもしたのですが、 "Reference to nonexistent group in regex"と\3をリファレンスとして とられてエラーになりました。 このような場合、どうすればヒットした文字のみを置換できるでしょうか。 非常に基本的なことなのですが、参考書やウェブではなかなか見つからな かったもので。。。。 よろしくお願いします。

    • ベストアンサー
    • Perl
  • 外部取得文字列と内部記入文字列のマッチング

    CSVなどからダウンロードした文字列とソース内に書いた文字列をマッチングさせようとしているがうまくいきません。 utf8で書かれたソース内でmy $a =('可')という文字列とcsvから取り込んだ文字列 my &b = ('可')をマッチングさせようとしているのですがうまくいきません。 use utf8を宣言してマッチングさせるには$bもしくは$bをどう変えればよいのでしょうか?

    • ベストアンサー
    • Perl
  • ある文字列を抜き出す方法

    perlを使ってるわけじゃないのですが perl互換の正規表現ができるソフトで a1.*?x2 という正規表現を抜き出すようにしたいのですが どうすればいいでしょうか? a1.*?x2 という文字列は、文章の中に複数でてきて 文章に規則性などもなく「a1」と「x2」の前後も決まった文字ではありません 「a1」と「x2」の間の文字にも特に規則性はありません 気持ち的には [^(a.*?x)]*? を削除すればいいのかな。って思ってやってみましたが 上手くいきません 置換とか、使わないといけないのかなと思いますが 今さっき解説を読んだばかりであやふやです よろしくお願いします

    • ベストアンサー
    • Perl
  • join と split で文字列を操作する場合

    にんにちは、 うまく解決する方法を思いつかないので、質問させてください。 以下のスクリプトを実行すると、a から z を * で join して、 その後、* で split するかなと思ったら、split は正規表現として とらえるためでしょうか、エラーになります。 #! /usr/bin/perl -w use strict; my $a = '*'; my $b = join $a , ('a'..'z'); print "$b\n"; my @result = split /$a/,$b; print "$_\n" foreach @result; exit(); $a = '\*'; にすると、split したときに、 余計な \ が残ってしまいます。 任意の(書く時点では分からない)いろんな文字列で 連結したり分割したりする場合のスマートな方法が ありましたら、教えていただけませんか? Perl 5.8 です。お願いします。

    • ベストアンサー
    • Perl
  • Perlの数値・文字列操作

    Perlで以下の16進数の連続した文字列を db444500 配列に入れて後からわかりやすい16進数で表示させたり、 foreach (@list){ print sprintf("%02X ", $_); } 直接文字列として、 0xdb, 0x44, 0x45, 0x00 と表示させるには、どのような書き方をすれば良いのでしょうか?

    • ベストアンサー
    • Perl
  • 配列から網羅的な文字列を生成するには?

    perlの配列を使った、網羅的な文字列生成について質問です。 ある特定の種類の文字のレパートリをつかった、n文字の文字列すべての組み合わせを生成したいと考えています。 例えば文字 A, B, C の三種類をつかった2文字の文字列なら AA,AB,AC,BA,BB,BC,CA,CB,CC 3x3 =9 種類というふうになります。 n=2の場合、 @array = qw(A B C); foreach $moji(@array){ $moji1 = $moji; foreach $moji(@array){ $moji2 = $moji; $mojiretu = $moji1.$moji2; push (@mojiretuset , $mojiretu ); }} print @mojiretuset; とするとforeachをふたつ重ねることで文字の組み合わせすべてを生成できました。 問題なのは、問題なのは、今私がしたいのは文字数nを(ループの)外から指定して(例えば$mojisuu = 6 などとして)n文字の場合の網羅的な文字の組み合わせを生じさせることなのです。 毎回自分でforeachを必要なだけ重ねて書き直す、というのは現実的ではありませんし、n個のforeachの入ったperlのコードを書くコードというのも避けたいのです。 文字数を自由に後から設定して、特定の配列から網羅的な組み合わせを生じさせるにはどのようなコードを書けばよいでしょうか?

    • ベストアンサー
    • Perl
  • 正規表現の中の変数の中の演算子

    perlで正規表現を使おうとしています。 確認したい文字列は変数にしており その文字列には「?」が含まれています。 ------------------------ $str = "文字列" $exp = "test?aaa=bbb"; if ($str =~ /^sss.*${exp}$/){ #do something } ------------------------ これだと、ヒットしません。。 $expを"test\?aaa=bbb"にすることもできません。 正規表現にはこだわりません。 どうしたら、うまくマッチングできますかね。。 なにか案があれば教えてください。

    • ベストアンサー
    • Perl
  • 正規表現でタグの中を除く文字をマッチングするには

    正規表現でタグの中を除く文字をマッチングするしたいのですが 良い方法はありますでしょうか。 例えば <a>のタグの中にない、"あい"を"かき"に変換したい。 <a>あいうえお</a>あいうえお ↓ <a>あいうえお</a>かきうえお という様にしたいのです。 正規表現では向かない処理かも知れませんが、 良い書き方ありましたら教えてください。

    • ベストアンサー
    • Java
  • 特定の文字列を削除

    こんにちは perlで特定の文字列からその後ろをすべて 削除したいのですが、うまくできなくて質問します。 Ex)123.12abc   ⇒123.12 012.123abc   ⇒012.123 123.1234|| ⇒123.1234 上記のようなデータの少数点までの数字の後ろにabc、||、半角、全角スペースなど文字列があります. 少数点までの数字の後ろの文字列すべてを削除したいですが、 特定の文字列からその後ろにある文字列全てを指定する方法(正規表現)はありませんでしょうか? どうかご存知の方、教えてください!! よろしくお願いいたします。

  • 文字列にコントロール文字を含むと何ができるの?

    プログラミングPerlを読んでいます。 ページをめくる速度が、すっごい遅いのですが・・・ やっとこさ74ページまできました・・・ 今回の疑問は文字列中にコントロール文字を埋め込むと何ができるの? というものです。 この疑問が浮かんだきっかけは このページでコントロール文字を表す正規表現が紹介されていたからです。 このような正規表現が用意されているということはコントロール文字を使用した文字列マッチを行うことを想定しているのだと思います。 すなわちコントロール文字を含んだ文字列を扱う場面が出てくるのだと思うのです。 このような文字列は、どのような場面で登場するのでしょうか。 また、どのような働きをするのでしょうか。 恐らく文字列を画面やプリンターへ出力するのと同時に、何か別の事柄を一緒に行うのではないかと予想しているのですが・・・ ちょっと気になったので質問しました。 どなたか教えてください。

    • ベストアンサー
    • Perl