• 締切済み

perl 最短マッチについて

以下のコードを実行すると ab が出力されますが理由が分かりません。 if('aabc' =~ /a(.*?)c/){print $1;} $1の部分は最短マッチなので期待値としては b が帰ってくるべきだと思うのですが、 何故このようなことになるのでしょう。(最短マッチは後方のみ有効?) 暇な方よろしくお願いします。

みんなの回答

  • entree
  • ベストアンサー率55% (405/735)
回答No.4

他の方も言われていますが、正規表現で文字列を探索するときは、 先頭から行なってマッチした時点で結果を返します。 文字列が'aabc' の場合、まずの1つ目の「a」でマッチするかどうかチェックします。 a ab c ( $1 eq 'ab' )でマッチするのでこれで打ち切りです。 確かに2つ目の「a」でもマッチしますが、そこまでチェックされません。 なので、「最短マッチは後方のみ有効?」ということになります。 ちなみに、期待されている動作にしたい場合は下記のように書く必要があるでしょう。 if('aabc' =~ /a([^a]*?)c/){print $1;} これなら1つ目の「a」ではマッチしませんから、$1 eq 'b' となります。

全文を見る
すると、全ての回答が全文表示されます。
  • ORUKA1951
  • ベストアンサー率45% (5062/11036)
回答No.3

あるいは、 $ perl if('aabc'=~/a([^a]*?)c/){print "$1\n";} if('aabc'=~/a([^a]*?)c/){print "$1\n";} 要は if('aabc' =~ /a(.*?)c/){print $1;} だと、aが見つかった時点で.*にマッチするものを探すという事です。当然aは.に含まれますから、期待通りabが出力される。 if('aabcaabbc' =~ /a(.*)c/){print $1;} と if('aabcaabbc' =~ /a(.*?)c/){print $1;} を比較するとよいかな

全文を見る
すると、全ての回答が全文表示されます。
  • ORUKA1951
  • ベストアンサー率45% (5062/11036)
回答No.2

私のperlはbが出力されますが?ただし、 if('aabc' =~ /a(.*?)c/){print $1;} じゃだめ。aがひとつと決めているから

全文を見る
すると、全ての回答が全文表示されます。
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

なるべく文字列の先頭に近い位置でマッチする場合を優先するから.

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

関連するQ&A

  • すべてにパターンマッチしてしまうのはなぜ?

    以下のようなスクリプトを書いた時に my @list = ('ab', 'cd', 'efg', 'hijk'); foreach my $line (@list){ #print "$line\n"; if ($line =~ m/ ^a| ^e| /x){ print "$line "; }} 標準出力は ab cd efg hijk となり、@list内の要素すべてにマッチしたことになってしまいます。 理由がわからずごちゃごちゃといじっていると、検索部分を =~ m// としても全く同じことになります。 これは、どの配列の要素も空(くう?)を含むためにヒットしてしまう・・・ ということなのでしょうか? どのように理解すれば良いのでしょうか?基本的な質問で申し訳ございませんが、どなたかよろしくお願い致します。

    • ベストアンサー
    • Perl
  • perl でこのマッチは失敗しますか?

    perl でこのマッチは失敗しますか? my $one = "FEFRGrgarGEEeg+05fweaEFJIEI+A"; my $str = "FEFRGrgarGEEeg+05fweaEFJIEI+A"; if($str =~ m/$one/){ print "same"; }else{ print "difference"; } exit; 5時間ほど悩んでそれらしいところを見つけたのですが、この部分で失敗しているようでした。 「+」記号がある為だと思うのですが、何故、このようなことになるのでしょうか? このように、失敗するような避けるべき文字ありますか? また、+記号などがあっても正しくマッチを使う方法はありますでしょうか?

    • ベストアンサー
    • Perl
  • 正規表現内での変数の扱いに関して

    正規表現内での変数の扱いに関して あるの変数の文字列が別の変数の文字列を冒頭に含むかどうか判別した上でその差分を抽出するコードを書こうとしています。 $a='komekoron'; $b='kome'; if($a=~/^$b(.+)$/){print $1}; このコードを実行すると「koron」が出力されます。 同様に以下のコードで「:」を出力させたいのですが上手くいきません。 $a='*:'; $b='*'; if($a=~/^$b(.+)$/){print $1}; 出力内容は「*:」 これは変数内の文字列がパタンとして扱われているのでしょうか。どうすれば意図する動作になるでしょうか。ご教授願います。

    • ベストアンサー
    • Perl
  • perl:パターンマッチを使ったifの条件

    perlでパターンマッチを使ったifの条件が必ずTRUEになってしまいます。 以下は条件です。二つのファイルがあって、片方のファイルのある列の文字列と別のファイルのある列の文字列が一致したら一致した行の1列目を出力するというプログラムです。 perl v5.12.3 『oct_gene.csv』は以下のような2列のファイルで、2列目であるalphabetの群は空白で区切られています。文字コードはASCIIです。 1 zinc finger protein of the cerebellum 3 0 stathmin-like 2 . . . . 『RNA.csv』は以下のような3列のファイルで、3列目のalphabet群は同じく空白で区切られています。文字コードはUTF-8です。 1 NM_324891 sin3 associated polypeptide 2 NM_53344 Nanog homeobox . . . open (WRITE, ">RNAseq_Oct.csv"); open(FILE, "RNA.csv"); while($line = <FILE>){ chomp $line; @fact = split /\t/, $line; open(OCT, "oct_gene.csv"); while($octline = <OCT>){ chomp $octline; @oct = split /\t/, $octline; if($fact[2] =~ /$oct[1]/){ print WRITE $fact[2] . "\t" . $oct[1] ."\n"; last; } } close (OCT); } close (FILE); close (WRITE); この中のif文がうまく働かず、whileで繰り返すまでもなく必ず if($fact[2] =~ /$oct[1]/) が成り立ってしまいます。 どなたか詳しい方、どうかご教示願います。 それではよろしくお願いします。

    • ベストアンサー
    • Perl
  • perl 5.8.8 日本語マッチ

    perl5.8.8を使っています。 日本語にマッチする正規表現を書きたいのですが、どうしてもマッチしません。 例えば、以下のファイルtest.txtから「さしすせそ」だけを抽出し、表示させたいです。 ---------test.txt-------------------------------- あいうえお かきくけこ さしすせそ たちつてと -------------------------------------------------- ----------test.pl-------------------------------- use strict; use warnings; open(FILE, 'test.txt') or die "$!"; my @file = <FILE>; close(FILE); foreach my $line (@file){ if($line =~ /^さ/){ print "$line\n"; } } ------------------------------------------------ このtest.plを実行しても「さしすせそ」を抽出することが できません。 どうしたらよいのでしょうか? 自宅の新しいバージョンのperlだとできるのですが 会社のperlは5.8.8で顧客環境でもあるのでバージョンアップも できません。 すみませんが、よろしくお願いいたします。

    • ベストアンサー
    • Perl
  • Perlの正規表現でマッチする範囲を限定

    例えば、以下のようなことがしたいのですが可能でしょうか? 変数$bufに複数行の文字列が入っていたとしてこのうち、 タグとエレメント外を対象にしてマッチさせる (例として以下のような文字列にしたい) <a href="abcdef">abcdef</a><br> <b>abc</b>defabcdef<br> abcdef<b>abcdef</b><br> ↓(タグとエレメント外の文字aを<b>a</b>に置き換える) <a href="abcdef">abcdef</a><br> <b>abc</b>def<b>a</b>bcdef<br> <b>a</b>bcdef<b>abcdef</b><br> 実際にはこのときのマッチの対象となる文字と文字数は可変で bになるかもしれないですしabとかになるかもしれません。 ネット上で検索していろいろ試してみたのですが惜しい ところまではいっても完全に正しく動作しませんでした。 (タグやエレメントの中身に反応してしまったり一部分が 置き換えされなかったり<br>タグの後ろが<b></b>のように なったり) 良いアドバイスください。 よろしくお願いします。

    • ベストアンサー
    • Perl
  • 文字列のマッチについて

    下記cgiで+、*、?が含んでいるとマッチしないんですが 正しいマッチのさせ方を教えてください。 それと+*?以外にもマッチしない文字があるのでしょうか? ---実行結果--- yy+yyは含んでいない yy*yyは含んでいない yy/yyは含んでいる yy-yyは含んでいる yyyyは含んでいる yy1yyは含んでいる yy=yyは含んでいる yy?yyは含んでいない yy&yyは含んでいる yy yyは含んでいる yy.yyは含んでいる ---Perl--- #!/usr/bin/perl print "Content-type: text/html\n\n"; print "<html><head><title>counter</title></head>\n"; print "<body>\n"; @data = ('yy+yy', 'yy*yy', 'yy/yy', 'yy-yy', 'yyyy', 'yy1yy', 'yy=yy', 'yy?yy', 'yy&yy', 'yy yy', 'yy.yy'); foreach $a (@data) { $b = $a; if ($b !~ m/$a/){ print "$aは含んでいない";print "<br>"; } else{print "$aは含んでいる";print "<br>";} } print "</body></html>\n";

    • ベストアンサー
    • Perl
  • perl初心者です。宜しくお願い致します。

    ファイルの容量が大きく。perlを使用してデータの集計をしています。 "A"がきたらflag1をたてなさい。 "B"がきたらflag2をたてなさい。 "C"がきたらflag3をたてなさい。 これでAとBとCを抜き取ること&AからCまでの時間を取得したのですが、 Bの数のmaxの値だけを抜き取りたいのですが、Bがきたときの数をすべて 出力してしまいます。下記の文だと、Bが4回きたら、1,2,3,4と出力してしまいます。 それで4だけを出力したいのですがどのように書き換えたらようか教えて頂けますでしょうか。 '----------------------------------------------------------------------------- open (IN,"< $ARGV[0].txt") or die; open (OUT,"> $ARGV[0]_out.txt") or die; $flag =0; my $a, $b, $c; $count = 0; ####################################################### while($line =<IN>){ ($time,$data) = split(/\s+/,$line); if($data eq "A") { $flag=1; $a = $time; #print OUT $line; #print OUT "\n"; } elsif($data eq "B"){ $flag=2; $count++; $count == $data; print OUT ("$count\n") } #print OUT ("$count\n"); elsif($data eq "C"){ $flag=0; $count=0; $b = $time; $c = $b - $a; print OUT ("time $c\n") } } -------------------------------------------------------------------------------

  • Application.Matchについて

    A1と同じものを検索するのにApplication.MatchとForNextを使って行いたいのですが上手く出来ません A1 7000  B1 500        B2 250        B3 7000        B4 350        B5 7000         B6 650        B7 7000        B8 870        B9 900        B10 340 とあって下のマクロを実行すると一番最初のしかでませんあるもの全部を検索したいのですがどうすれば良いですか教えて下さい Sub Sample3() Dim ret As Variant For i = 1 To 10 ret = Application.Match(Range("A1"), Range("B1:B10"), 0) Cells(2, 5) = ret Next If IsError(ret) Then MsgBox "該当データが見つかりません" Else MsgBox ret & "番めのデータです" End If End Sub

  • パターンマッチについて

    perl初心者です。文字列がパターンマッチするかを検査したいのですが、検査文字列にカッコ"()"が含まれているので期待する結果を得られません。(マッチしているように見えるが実行結果はマッチしていないになる)カッコによりパターンがグループ化されているように思えるのですが。原因と対処をご教示ください。 $word = "Remote Procedure Call (RPC)" $chk_word = "Remote Procedure Call (RPC)" if ($word =~ m/$chk_word/ ) {・・・・ よろしくお願いします。

    • ベストアンサー
    • Perl