• ベストアンサー

文字クラス外部のメタ文字 「?」

"/\b([AIUEOaiueo].*?)\b/"が何を言っているか分かりません。 //…正規表現は//で囲む \b…文字クラス外部に記入されるもので単語の境界を表す。    ([AIUEOaiueo].*?)という正規表現文字列で検索対象文字列を検索する。 ()…文字クラス外部に書かれて、サブパターンを意味するようですが、    サブパターンとはグループ化と同じ意味で、ここでは、グループ化して単語([AIUEOaiueo].*?)と書いているのでしょうか? []…[AIUEOaiueo]は先頭文字がAIUEOaiueoの文字 . …改行を除く全ての文字にマッチ * …0回以上の繰り返し。    この場合、"."で表されている改行を除く全ての文字の繰り返し。 ? …"("の意味を拡張。0回または1回の繰り返し。最短マッチ。    という意味のようですが、分かりません。この"("は何ですか?   検索対象文字のAmerica,Englandを表示させるのに"/\b([AIUEOaiueo].*)\b/"ではダメなのでしょうか? 検索対象文字は「"Japan" "America" "France" "England"」です。

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

  • ベストアンサー
回答No.2

「()」は後方参照用のくくりです。 グループ化は 「(?:)」と記述します。 後方参照に関しては、 preg_match("/\b([AIUEOaiueo].*?)\b/", 'America', $match) とした場合、$matchに「()」でくくった部分にマッチした文字列が入ります。 ためしに、print_r($match)としてみてください。 また、「20-50-40」となっている文字列を「50-20-40」と並び順を入れ替える置換を行いたいとした場合 $result = preg_replace("/([0-9]+)\-([0-9]+)\-([0-9]+)/", "$2-$1-$3", '20-50-40'); とすると、「()」区切りのものを先頭から、$1,$2,$3・・・として後から参照することが出来るようになり、意図した置換が行えます。 >検索対象文字のAmerica,Englandを表示させるのに"/\b([AIUEOaiueo].*)\b/"ではダメなのでしょうか? この件に関しては問題ないです。 むしろ、"/\b[AIUEOaiueo].*\b/"で良いと思います。 最短マッチに関して、もう少し判りやすいものを書きますと ------------------------------- <div>hoge</div><div>hogehogemoge</div><div>hogehoge</div> ------------------------------- とHTMLタグがあったとして、「<div>hoge</div>」が検索されてくることを想定して、 if(preg_match("/<div>(.*)<\/div>/", $str, $match)){ print_r($match); } と書いたとします。 その場合、print_rで$matchを見ると、「hoge</div><div>hogehogemoge</div><div>hogehoge」が検索されてきているのが分かると思います。 基本的に正規表現は最長でマッチします。 なので、 if(preg_match("/<div>(.*?)<\/div>/", $str, $match)){ print_r($match); } としてやると、一番最初に</div>が出現したところ(最短)までを検索し $matchも 「hoge」となります。 以上です。

peiee
質問者

補足

回答ありがとうございます。 検索対象文字は「"Japan America France England"」と間違えていました。そのため"?"が付く付かないで違っていました。質問を間違えてすいません。 説明を沢山していただき、また質問が発生しました。 if(preg_match("/<div>(.*?)<\/div>/", $str, $match)){ print_r($match); } ですが、実行すると、 Array ([0]=> hoge [1]=>hoge) と表示されるのですが、0行と1行に値が入ったのですか? なぜ2つもセットされているのでしょうか? $result = preg_replace("/([0-9]+)\-([0-9]+)\-([0-9]+)/", "$2-$1-$3", '20-50-40'); ですが、"-"の前に"\"が付いているのですが、"\"はメタ文字の特別な意味をなくすそうですが、"-"はメタ文字なのかと"\"をとって実行しても結果は"50-20-40"と表示されました。

その他の回答 (4)

回答No.5

>rはどこにいったのでしょうか? /([AIUaiu].*?)([EOeo].*?)/ この正規表現の意味していることを日本語に直してみるのが手っ取り早いですね。 「A」「I」「U」「a」「i」「u」のうちいづれか一つの文字が使われており、 その次の文字が何らかの文字0文字から「E」「O」「e」「o」が出現するまでの間で、 その次の文字が何らかの文字0文字以上から無指定(?の後ろに何も指定が無いため)の最短の値(つまり0文字)にマッチする。 ということになります。 となると、apan Ameで、「r」が取得されないのは最短の値(0文字)を引いてしまった為ですね。 rがどうしても必要なのであれば、 /([AIUaiu].*?)([EOeo].+?)/ と指定する必要があります。 「*」は0文字以上 「+」は1文字以上 です。

peiee
質問者

お礼

"Japan America France England"の検索で /([AIUaiu].*?)([EOeo].*?)/の場合 配列番号 [0][0] apan Ame 一回目"a"から"e"までを検索した。 [0][1] ica France 二回目"a"から"e"までを検索した。 その後は[AIUaiu]はマッチしても、 その後ろに[EOeo]が続かないので検索終了。 =================================== "Japan America France England"の検索で /([AIUaiu].*?)([EOeo].+?)/の場合 配列番号 [0][0] apan Amer 一回目"a"から"e"までを検索した。([EOeo].+?)なのでrが付く。 [0][1] ica France 二回目"a"と"e"までを検索した。eの後ろ一桁はスペース [1][0] apan Am [1][1] ica Franc [2][0] er [2][1] e 検索するのは[AIUaiu]から[EOeo]で、 後ろの".*?"".+?"は、セットするにはどこまでセットするか という意味ですね。ありがとうございました。<m(__)m>

回答No.4

「\-」の件、-は[a-z]とした場合、aの値からzの値までを人くくりにする場合に特別な意味合いを持ちます。 今回の場合明らかにそのような意味合いは持たないので、「\」とするのは不必要ですね。すみません。 そして下記、ご回答です。 preg_match_all関数とpreg_match関数は別物になります。 preg_match関数は一番最初にマッチした時点で動作が完了し、 preg_match_all関数はマッチできる文字があった場合に再帰的に全てマッチします。 preg_matchで値を取得した場合 [0]"America" [1]"Am" [2]"erica" と取得されると思います。 preg_match_allで値を取得した場合 [0][0]"America" [1][0]"Am" [2][0]"erica" と取得されます これは後方参照に渡す値を基点としているからです。 つまり [後方参照用の値][何番目にマッチしたか] => 文字列 となります。 配列番号 [0][0] apan Ame [0][1] ica France [1][0] apan Am [1][1] ica Franc [2][0] e [2][1] e と取得されたのであれば 最初にマッチしたのが、「apan Ame」であり、2番目にマッチしたのが、「ica France」です。 最初にマッチした「apan Ame」の中で最初に「()」でグルーピングしたものが「apan Am」で、最初にマッチした「apan Ame」の中で2番目に「()」でグルーピングしたものが「e」ですね。

peiee
質問者

補足

if(preg_match_all("/([AIUaiu].*?)([EOeo].*?)/",$var,$result)){ の場合、 配列番号 [0][0] apan Ame [0][1] ica France とマッチしていますが、rはどこにいったのでしょうか? なぜこのように取得したのか理解できません。 宜しくお願いします。<m(__)m>

回答No.3

>なぜ2つもセットされているのでしょうか? 配列番号0のものは、正規表現全体でマッチングされた文字列が挿入されそれ以降のものは、「()」でくくったグループがそれぞれ切り出されて挿入されます。 preg_replace関数での例を参考にしてもらいますと、後方参照用の値が「$1」「$2」・・・と始まっているのが分かると思います。 これと配列番号が連動している感じです。

peiee
質問者

補足

<?php $var="Japan America France England"; if(preg_match_all("/\b([AIUaiu].*?)([EOeo].*?)\b/",$var,$result)){ print_r($result); }else{ print(一致しませんでした。); } ?> を実行すると、 Array ( [0] => Array ( [0] => America ) [1] => Array ( [0] => Am ) [2] => Array ( [0] => erica ) ) と表示されました。 配列番号0のものは、正規表現全体でマッチングされた文字列が挿入されるそうですが、 結果は、 配列番号 [0][0] America [1][0] Am {2}{0] erica でした。 最短マッチで一単語マッチングして、0行にAmerica 最初の()の検索でAIUaiuにAがマッチ。次の()の検索でEOeoにeがマッチ。 よって、[1][0]はAmまで。[2][0]はericaという処理をしたのでしょうか? ==================== <?php $var="Japan America France England"; if(preg_match_all("/([AIUaiu].*?)([EOeo].*?)/",$var,$result)){ print_r($result); }else{ print(一致しませんでした。); } ?> を実行すると、 Array ( [0] => Array ( [0] => apan Ame [1] => ica France ) [1] => Array ( [0] => apan Am [1] => ica Franc ) [2] => Array ( [0] => e [1] => e ) ) と表示されました。 結果は 配列番号 [0][0] apan Ame [0][1] ica France [1][0] apan Am [1][1] ica Franc [2][0] e [2][1] e これは、どのように処理をしたのでしょうか?

  • notnot
  • ベストアンサー率47% (4900/10358)
回答No.1

*? で最短マッチです。「"("の意味を拡張」という記述は間違いです。 対象文字列が"America"のように一語のものだけなら、* でも同じですが、 対象文字列が、"America Washington" の時、 /\b([AIUEOaiueo].*)\b/ は、"America Washington"全体にマッチし、 /\b([AIUEOaiueo].*?)\b/ は、"America"にマッチします。

peiee
質問者

お礼

最短マッチが何か分かりました。ありがとうございました。

関連するQ&A