• ベストアンサー

正規表現の o

Perl正規表現の =~ s/aaa/g の g が o だったのを見たことがあります。 o はどういう意味なんですか?

  • A__
  • お礼率59% (194/328)
  • CGI
  • 回答数2
  • ありがとう数5

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

  • ベストアンサー
  • kokucho81
  • ベストアンサー率61% (157/255)
回答No.2

ああ、それは、変数部分の展開を一度しか行わないということです。 例を出してみましょうか。 ############################# foreach(0..20) { if ($_=~/$_/) { print "Match\n"; } else { print "No Match\n"; } } ############################# このようにすれば、当然20回 Match とでるでしょう。 なぜなら、$_の中に$_の中身が含まれているのは、理の当然だからです。 しかし、 ############################# foreach(0..20) { if ($_=~/$_/o) { print "Match\n"; } else { print "No Match\n"; } } ############################# こうすると、0回目、10回目、20回目だけがMatchして、 あとはNo Matchとでます。 これは、はじめのマッチングで$_が0として展開され、以後 これを使いつづけるのです。 10回目、20回目でMatchと出ているのは、はじめの「0」という文字が 「10」と「20」という文字列に含まれているからですね。 このような変数の中身を固定化してしまう機能があるのは、 スピードアップのためです。 (まぁインタプリタであるPerl言語でスピードアップして  どの程度意味があるのかという根本的な問題はありますが。。。) 今回の様な例では、変数の中身が変わってしまうため、 期待しない結果となってしまいますが、該当のマッチング処理の際に 変数の中身が変わらないことがわかっている(例えば、マッチングの間 はずっと $_ は "ABC"である、など)のであれば、「o」オプションを つけることでスピードがアップするというわけです。 (まぁ、本当にごくごくわずかですけれど。。。  むしろやたらめったら「o」つけていると、後で機能拡張したときに  なんでバグってんのか見つけにくいエラーが潜んでしまいますね) あとは、実際に使って動きを確認して行けばわかることです。

A__
質問者

お礼

ありがとうございます。 o を使うととても変わった動作になるんですね。 スースを書いてもらえたのでよく分かりました。

その他の回答 (1)

  • yuizuian
  • ベストアンサー率42% (103/245)
回答No.1

正規表現…というか、マッチングですね。 えぇと、私もあまり詳しくなくて申し訳ないのですが、 aaaの部分が正規表現で書かれていた場合、それを1度だけ展開するそうです。

A__
質問者

お礼

ありがとうございます。 昔、1回だけ見た記憶があったんだけど o というはやっぱり存在していたんですね。

関連するQ&A

  • Perlで使える正規表現を教えて下さい。

    Perlで使える正規表現を教えて下さい。 半角英語で、小文字が3文字以上続いた後、大文字が来る場合、その大文字の右にスペースを入れる。 これをPerlで使える正規表現を教えて頂けないでしょうか? 例 $str = 'AaaAaaaBbbbbCccccDddBbA'; # Aaa Aaaa Bbbbb Ccccc DddBbA ちなみに、色々ネットで調べて試してみて、 $str =~ s/([a-z])([A-Z])/$1 $2/g; が最も近いコードになったのですが、2文字続いただけでもスペースが入り困っています。 宜しくお願い致します。

    • ベストアンサー
    • Perl
  • 正規表現の o オプションの意味が分かりません

    正規表現の質問です。 言語はPerlで組んでいます。 いくつかのhtmlファイルを順に開き、以下のようなコードを実行します。 $http{BODY}=~ /(?<=\[ No\.)([0-9]{$digit})(?= \/ $num)/o; ここで $http{BODY} 読み込んだhtmlファイル $digit 変数。整数値。 $num 変数。整数値。 この正規表現で、 ・・・・[ No.2 / 3 ]・・・・ といった感じの文字列から、この場合は「2」をマッチさせようとしました。 ところが最初に読み込んだファイルではうまくマッチしたのですが、2番目のファイルではマッチしません。 o オプションを外すとうまくいきました。o オプションは変数展開を1回行うとのことです。元のファイルはやたらとでかいので、o オプションを付けたら少しは早くなるかなと思いつけていたのですが。。。 ネットで調べると、 while( $s = <FH> ){ # 一度だけ展開する if ( $s =~ /$arg/o; ){ .... } このような用例で、$argは変数というよりも、セットされた文字列として評価されるとあります。でも前述の正規表現の2つの変数、$digitと$numは普通に値を書き換えられていましたけど。。。 それとも o オプションを付けた正規表現では、その正規表現を処理するためのメモリ領域に一度変数の値を取り込むと、二度と読み込むことをしないということでしょうか。だから変数の値が変わっても、正規表現が用いるメモリ領域の値は変化しない。。。 でも $http{BODY}=~ /(?<=\[ No\.)([0-9]{$digit})/o; だったらちゃんと$digitの値が変わったことに対応しているんです。他にもいっぱい o オプションを付けた正規表現を用いていますけど、全部正常に作動しています(バグに気づいていないだけかもしれませんけど)。 前述の正規表現とこれら正常に作動する正規表現の違いは、後者が変数1個であるのに対して、前者は2個であるということです。「変数展開を1回行う」の意味は、変数1個にしか対応しないという意味なのでしょうか。でも前者も最初のファイルだけなら2個の変数に対応しているのです。 どういうことなのでしょう。

    • ベストアンサー
    • Perl
  • Perl正規表現わかりますか?

    下記のPerl正規表現ですが、どんな意味か分かるでしょうか? $var =~ s!/([^/]+|~(\.\.))/\.\./!/!g 参考書も読んでみたのですが分かりませんでした(セットされている文字列にどんなマッチング、置換をしているのでしょう) お分かりの方いれば、よろしくお願いします。

    • ベストアンサー
    • Perl
  • 正規表現が読めない

    諸般の事情でperlスクリプトに手を入れることになりました。 perlについてはまったくの素人であることに加えて、正規表現が読めません。お恥ずかしいのですが、下記を読み下していただけないでしょうか。 (変数のリスト) = map{/^"(.*)"$/ ? scalar($_ = $1, s/""/"/g, $_) : $_} ($tmp =~ /("[^"]*(?:""[^"]*)*"|[^,]*),/g); $tmpはカンマ区切りのテキストです。

    • ベストアンサー
    • Perl
  • Perlの正規表現について

    Perlの正規表現について質問です. ■質問 aaa bbb aaa bbb ccc "ddd" aaa bbb ccc "ddd eee" aaa bbb ccc ddd eee "fff ggg hhh iii" というような,文字列が書かれているファイルがあるとします. ※ダブルクォーテーションが無い行もあります. ※ダブルクォーテーション内のスペースの数は,行によってそれぞれ異なります. これを,ダブルクォーテーションの中にあるスペースだけ アンダーバーに置換する場合の正規表現を教えて下さい. つまり,下記の出力にしたいです. aaa bbb aaa bbb ccc "ddd" aaa bbb ccc "ddd_eee" aaa bbb ccc ddd eee "fff_ggg_hhh_iii" ■条件 ※ちょっと古いPerlでも動くよう,ゼロ幅肯定/否定後読((?<),(!<))は使わないでください. ※単に実現するだけなら, # cat inputfile | print -pe 'sub f(){}(shift;s/ /_/;return $_;); s/(\".*\")/&f($1)/e;' みたいな感じで置換できそうですが,「正規表現だけで簡単に書けるかどうか」が知りたいのです(正規表現だけで実現出来る場合,そのアルゴリズムを知りたいです).そのため,関数と/eオプションは使わないでください.

    • ベストアンサー
    • Perl
  • 正規表現の使い方

    $input =~ s/[a-z][0-9]-[0-9]/ [a-z][0-9]-[0-9] /g; perl言語での正規表現についてです。 置換に関してなのですが、このような使い方はできないでしょうか?? [a-z][0-9]-[0-9]にヒットしたものの前と後ろにスペースを代入したいのですが、何かいいプログラミングはないでしょうか?

  • 正規表現の 「 * 」

    正規表現の 「 * 」は、直前パターンの繰り返しですよね? つまり、a* は a, aa, aaa, aaaa, aaaaa, ..... にマッチするわけですよね? ところで、 echo abbbaaa | sed 's/a*/x/g' のようにしたら a, aaa の部分が x に置き換わって  → xbbbx となることを期待していたのですが、  → xbxbxbx となってしまいました。 なぜでしょうか?

  • perlでの正規表現について教えてください。

    たとえば、 $A = 'aaa/bbb/ccc/ddd/eee/fff/ggg' というものがあったときにperlの正規表現でddd/のすぐ後の部分を抜き取って違う変数に入れたいのですが、それを正規表現で切り取りたいのですが、どうしたらいいかわからないです。 初歩的な質問ですが、お答えいただければ幸いです。 よろしくお願いします。

  • (?:系の正規表現

    perlの正規表現で以下の意味は、ABC01かABC99のみマッチするということでよいでしょうか? /^ABC(?:01|99)$/ (?:は$1など使用しない場合に用いるで正しいでしょうか? (?系の正規表現について知識不足ですが、一覧や詳しい書籍がありましたら教えてください。 昔、 /^ABC01|99$/ とかいて、ABC99がマッチせず、99がマッチしたので、|を使うときは、()を書いたのですが$1など変に作用させたくなかったので、最近(?:系の存在を知ってもっと詳しく知りたくなりました。 (?:はPerlの正規表現特有のものでしょうか?

    • ベストアンサー
    • Perl
  • 配列を対象にして正規表現の置換、うまくいきません

    正規表現の置換ができませんのでお教え下さい。 @list= ('aaa', 'bbb', 'ccc'); $sentence = 'rrr bbb dddd eee aaa rrrr bbbb aaa'; foreach (@list) { $sentence =~ s/$_/あああ/g; } print $sentence; どうしてもエラーになります。 そこで \をつけて、$sentence =~ s/\$_/あああ/g; などとやってみても置換されません。 どこが間違えているのでしょうか。よろしくお願いします。

    • ベストアンサー
    • Perl

専門家に質問してみよう