• ベストアンサー

正規表現preg_matchでincrement?

foreach($data as $key=>$val) { if(preg_match("/^increment\((\-?\d+)\)$/i",$val,$m)) $q.= "`$key` = `$key` + $m[1], "; ・上記のようなif文があるのですが、どういう意味でしょうか? ・incrementはカウントアップ? ・$valに「-1」…「-9」文字列があれば、$m[1]として利用? ・iがあるので、その際、大小文字の違いを無視?

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

  • ベストアンサー
noname#244856
noname#244856
回答No.3

マニュアル http://www.php.net/manual/ja/reference.pcre.pattern.syntax.php まずPHPの正規表現パターンの基本から。 /パターン/ のように記号で全体をくくります。よく使われるのは「/」ですが、 実は「\」以外なら何でも良いです。 「/」以外だと「#」「~」「@」あたりがよく使われます。 /パターン/i 後ろについてるのはパターン修飾子です。 「i」は半角アルファベットの大文字小文字の区別しません。 この正規表現は一応動作するのですが、無駄なエスケープが行われていたり、逆にエスケープすべきところが足りてなかったりするので、「正しい」正規表現に書き直すとこうなります。 PHPコード "/^increment\\((-?\\d+)\\)$/i" これがPHPに文字列リテラルとして評価されると、 /^increment\((-?\d+)\)$/i となります。 【変更点】 1. 「-」に関して エスケープが不要なので「\」を消しました。 2. 「\」に関して 以下のコードを見比べてください。 PHP http://ideone.com/0wBB9d C言語 http://ideone.com/f2A7Es C言語では「\」はどんなときも必ずエスケープしなければなりません。 PHPではそうではないのですが、PHP以外の他の多くの言語ではそうなってます。 初心者が混乱を招くもとなので、私はPHPでしか出来ないこの書き方は可能な限り避けています。 PHPに評価された後の文字列リテラルについて、順に追って説明します。 「^」は文頭であることを表す。マッチング対象の1文字目がかならずここに来なければいけないという制約。 「increment」はただの文字列。 「(」はサブパターンを表すメタ文字だが、「\(」とエスケープすることによってただの「(」という文字を表すようにしている。 その次の「(」でサブパターン開始。 「-」はただの文字列。 「?」で直前の文字(ここでは「-」)があってもなくてもいいことを表す。 「\d」は半角数字。 「+」で直前の文字(ここでは「\d」)の繰り返し(最長マッチ)を表す。 「)」でサブパターン終了。 「)」はサブパターンを表すメタ文字だが、「\)」とエスケープすることによってただの「)」という文字を表すようにしている。 「$」は文末であることを表す。マッチング対象の最後の文字がかならずここに来なければいけないという制約。 よってマッチする文字列の例として、 "increMent(-1)" "inCremEnt(05)" などが挙がります。 マッチング結果は $m に代入されます。 ここでは、 $m[0] … 全体 $m[1] … 1つ目のサブパターン となります。 "increMent(-1)" の場合は、 $m[0] = "increMent(-1)"; $m[1] = "-1"; という内容になります。 全て文字列扱いです。 preg_match関数は、以下の返り値を返す可能性があります。 ・マッチした時 … 1 ・マッチしなかった時 … 0 ・パターンが正規表現として間違っていた解 … FALSE そのままif文に返り値を突っ込むと、マッチした時のみTRUE、あとの2つはFALSEと評価されます。 $q .= "`$key` = `$key` + $m[1], "; これどこが変数展開されるか分かりにくくて見にくいですね。 $q .= "`{$key}` = `{$key}` + {$m[1]}, "; 個人的には { } で明示したほうが見やすいと思います。

re97
質問者

お礼

回答ありがとうございました。 説明が丁寧で、とても分かりやすかったです。 大変参考になりましたー

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

その他の回答 (2)

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.2

> ・上記のようなif文があるのですが、どういう意味でしょうか? http://php.net/manual/ja/control-structures.if.php ifには if(式) 文 という構文があります。単文なら{}は不要です。 ただ、{}を付ける方が好まれます。 if(preg_match("/^increment\((\-?\d+)\)$/i",$val,$m)) { $q.= "`$key` = `$key` + $m[1], "; } > ・incrementはカウントアップ? iのあとにn,そのあとにc,そのあとにr,... という、ただの文字列です。 PCREの正規表現で、単語が意味を持つのは、文字クラス( [:クラス名:] の形式で使用 )くらいです。 http://jp2.php.net/manual/ja/regexp.reference.character-classes.php > ・$valに「-1」…「-9」文字列があれば、$m[1]として利用? 正確に言えば、(\-?\d+) が「1 番目のキャプチャ用サブパターン」になります。 この正規表現全体にマッチしたうちの、このサブパターンに一致する部分が$m[1]になります。 http://jp2.php.net/manual/ja/function.preg-match.php > iがあるので、その際、大小文字の違いを無視? そうです。 http://jp2.php.net/manual/ja/reference.pcre.pattern.modifiers.php

re97
質問者

お礼

回答ありがとうございました。 >PCREの正規表現で、単語が意味を持つのは、文字クラス( [:クラス名:] の形式で使用 )くらいです リンク先、参考になりましたー

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

$valの中身が increment(数字) に該当するかif文で判定しています。 数字部分は十進数の数字で正の数字でも負の数字でもマッチします。 \-? はマイナス記号が0回か1回の出現にマッチするので、マイナス記号が無くてもマッチします。 incrementは単純にそのような文字列があるかを判定しており、正規表現上特別な意味はありません。 preg_matchの第三引数は、正規表現の中で ( ) で囲んでいる部分にマッチした値を配列にして返してくれる変数を指定するものです。 $m[0] はパターン全体にマッチした文字列、$m[1] は1つ目のカッコに囲まれた範囲の値が入りますので、パターン文字列の \-?\d+ に該当する部分が入ります。 パターン修飾子の i はアルファベットの大文字小文字を無視してどちらにもマッチするようにしてくれるので、 increment という文字については大文字でも小文字でもマッチします。(全部大文字だろが、どこか1文字だけ大文字だろうがマッチします)

re97
質問者

お礼

回答ありがとうございました。 >incrementは単純にそのような文字列があるかを判定しており、正規表現上特別な意味はありません 参考になりましたー

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

関連するQ&A

  • preg_matchの正規表現がうまくいかない

    たとえば、http://gehasoku.com/?p=2のソースコードには ------------------- <rdf:Description rdf:about="http://www.com/aaa.html" trackback:ping="http://www.com" dc:title="タイトル" dc:identifier="http://iii.com/bbb.html" dc:subject="ハードウェア" dc:description="1 名前:名無しさん " dc:creator="soft_net" dc:date="2012-02-21T20:05:01+09:00" /> ------------------- のような形の<rdf:Description~~~/>タグの情報ががいくつかあると思います。これらすべてを文字列として取得したくて、次のようなphpを作成しましたが、うまく動作しません。 原因はどうやらpreg_match_allの正規表現がうまくいっていないからのようですので、 <rdf:Description~~~/>を抜き出すことができる正規表現を教えてください。 自分でもここでチェックしながらやりましたが、 http://www.rider-n.sakura.ne.jp/regexp/regexp.php <rdf:Description~をマッチすることはできても、/>で閉じることができませんでした。 よろしくお願いします。 <?php $url="http://gehasoku.com/?p=2"; $html=file_get_contents($urls); preg_match_all("/<rdf:Description(.*)?\/>/",$html,$match); print_r($match); foreach($match[1] as $value){ echo $value; } ?>

    • ベストアンサー
    • PHP
  • += -= *= /= を判別する正規表現

    PHP5.2.4を使用しています。 $key = 'a +='; $val = 2; の場合に、 a = a + 2 となるように変換するためには preg_match(ここに何か記述, $key, $match)を使ってどのように記述すれば良いのでしょうか? 例えば、次の条件だったら $key = 'a -='; $val = 2; a = a - 2 と変換したいです。 if (preg_match(ここに何か記述, $key, $match)) {  ここで$keyと$valと$matchを使って  a = a (+ or - or * or /) 2となるように記述すると思うのですが }

    • ベストアンサー
    • PHP
  • preg_matchでの コンマ について 

    phpでの正規表現で 「もしも変数$wordへ入力した文字列が Japan's という文字列に一致すれば」というスクリプトを作成しましたが、うまくいきません。 if(preg_match("/japan\'s/i",$word,$match)){ この Japan's における カンマの取り扱いを このケースではどうしたらいいかよくわかりません。 \' としてみましたが、うまくいきません。 なにかアドバイスやヒントがありましたら、よろしくお願いします。 ああでもない、こうでもないとやってみましたが、その過程で 唯一 Japan's にヒットしたのは、次のスクリプトでした。 if($word=="japan\'s") ただし、これは正規表現は使っていないわけですよね。 なにか、自分のローカル環境に問題があるのかと思い、レンタルサーバーに同じものをuploadして試して見ましたが、やはり結果は同じで、ヒットしませんでした。別のパソコンでもやってみましたが、結果は同じでした。 整理しますと、 (preg_match("/japan's/i",$word,$match) ではヒットせず、よって コンマの前に\をつけて(preg_match("/japan\'s/i",$word,$match) としましたが、これもヒットしなかったということになります。 1) (')は正規表現の特殊文字でないはずですから、そのまま使えるはずだと思いましたが、なぜかこれが使えない。 2) しかも、その前にエスケープの \ をつけても、そのエスケープ が効かないのはなぜか。 追記: 最近分かったこと。 おもしろいことに、 'j すると、hitする。でも、j' とするとヒットしない。 ということは、コンマ自体には問題ないのだろうと推測しています。でも、文字の後にコンマがつくと、preg_matchにとって特別な意味を持つ文字列に変わるのではないか。

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

    今現在、PHPの勉強をしているのですが preg_match("/\nFrom:\s*(.+)\r/i", $sss, $aaaa) という文字列が出てきて困っています。 preg_match関数における\nFrom:とは一体何なんでしょうか。教えてください。

    • 締切済み
    • PHP
  • PHPの preg_grep関数(正規表現)について

    こんにちわ, 今PHPで 配列$valに val[0]-> 'HOGE' val[1]-> 'HOGE' val[2]-> 'Time' val[3]-> 'Total' val[4]-> 'Time' val[5]-> '->' val[6]-> '00:00:02' と入っているときにpreg_grep関数を使用して,$time配列にval[6]の時間のフォーマットをした文字列を入れたいのですが, $time = preg_grep("/(..):(..):(..)/",$val6); としても,$time[0]にはうまく入りません。 どこが悪いのでしょうか。 ちなみに,正規表現のいいHPなどがあればついでに教えてください。 よろしくお願いします。

    • ベストアンサー
    • PHP
  • 正規表現で切り出せません。 < と > の間?

    宜しくお願いいたします。 PHP5.1.6です。 メールの受信をするときにメールアドレスだけを切り出したいのですが うまく出来ません。 【例-1】の様に、すると < > の間が表示するのですが 【例-2】の例のように、変数を入れると何も表示しません。 【例-1】で使用した文字列は、【例-2】の$from を echo で表示させたものをコピーしています どのようにしたらいいでしょうか? 宜しくお願いいたします。 【例-1】 $test="教えてお名前 <****@*******.com>"; $pattern = "<(.*)>"; if (preg_match( "/".$pattern."/i", $test, $match ) ){ //$from0 = $match[0]; $from1 = $match[1]; //echo $from0; echo $from1; } これで、うまく echo $from1 でメールアドレスだけ表示してくれます。 *** なぜか、$from0 には元の文字列は表示しませんが。 置き換える元の文字列を下記変数に変えると表示しません。 【例-2】 $mboxes = imap_check($mbox); $head = imap_header($mbox, $i); $from = htmlspecialchars(mb_decode_mimeheader($head->fromaddress)); $pattern = "<(.*)>"; if (preg_match( "/".$pattern."/i", "$from", $match ) ){ //$from0 = $match[0]; $from1 = $match[1]; //echo $from0; echo $from1; } **$from の所は "" で囲んだり、外したりしましたが一緒でした。

    • ベストアンサー
    • PHP
  • 正規表現かsplit、foreachのどれかでエラーになる

    MySQLのデータを並び替える文を作っています if(preg_match("_","$_GET[o]")){ $row = split("_","$_GET[o]"); }else{ $row = "$_GET[o]"; } foreach($row as $val){ ...... } このように書いたり、1行目のpreg_matchをeregに変えたりするとpreg_matchのところなのかsplitなのかそのあたりでエラーが出ます。 $row = split("_","$_GET[o]"); foreach($row as $val){ ...... } このように変えるとsplitが実行されたときにエラーになります(_がないときはスルーで問題なし) なので、おそらく$rowの型なのなんなのか分かりませんが、それが良くないと思うのですが、これはどうすればエラーが出なくなるのでしょうか。 エラーそのものの内容は少し先の ところが対象と思われる mysql_fetch_array(): supplied argument is not a valid MySQL result resource となるのですが、これはforeachのなかでMySQLのOrder by文節をまとめているので、それが影響してのことだと思います。 つまりは、foreachにかける$rowの問題だと思うのですが・・・ どなたかお分かりの方ヒントをください。 perl(MySQLは触らず)からphp&MySQLへの乗り換え中でphpは初心者です

    • 締切済み
    • PHP
  • 正規表現について

    PHP5.2.4を使用しています。 任意の数の引数がある文字列をpreg_matchを使ってマッチさせたいのですが、 例えば"ENUM(ab,cd)"は ab と cd の2つの引数があるとします。 次のようなパターン文字列まではアイデアとして浮かんだのですが、 引数の最後は , がないので当然ですがマッチしません・・・ どのようにパターン文字列を記述すれば良いのでしょうか? $str = "ENUM(ab,cd)"; if (preg_match("/ENUM\(([^\,]+\,)+\)/", $str, $match)) { print "{$match[0]}<br>\n"; }

    • 締切済み
    • PHP
  • 正規表現のコーディングについてお願いします。

    こんにちは、よろしくお願いいたします。 正規表現パターンを書く場合に皆さんがどのようにされているか教えてください。 例えば(ちょっとムリヤリ感が強いですが)、'Price \5800-' という文字列の \5800 の部分に preg_match でマッチさせたいとします。 単純に考えると、 /\\\d+/ のようなパターンが思いつくのですが、それを文字列として preg_match に渡す際に、コードはどのように書かれますか? <?php   $str = 'Price \5800-';   //とりあえず、'/\\\d+/' と書き、'/\\\\\\d+/' と、\ をそれぞれの \ に書き足す   if ( preg_match('/\\\\\\d+/', $str, $match) ) {     print_r($match);   } ?> 「まず、パターンを書き、全ての \ の前に \ を書き足す。」というのが無難なのかな?と思い、そうしていますが、 そういった考え方で間違っていないでしょうか? どうぞよろしくお願いいたします。

    • 締切済み
    • PHP
  • PHPの正規表現「preg_match」で漢字を含む場合のマッチパター

    PHPの正規表現「preg_match」で漢字を含む場合のマッチパターンについて 宜しくお願い致します。 preg_matchを使っての正規表現で、「あいうえおかきくけこ3月10日さしすせそ」という文字列から「3月10日」だけを抽出するには、どういうパターンが良いのでしょうか? 下記の様にやってみましたが、だめでした。。。 preg_match("/\d{1,2}[月]\d{1,2}[日]/",$hoge,$match) これではうまくいきません。 どなたかお助けくださいー!

    • ベストアンサー
    • PHP