PHPにおける正規表現の活用方法

このQ&Aのポイント
  • PHPにおける正規表現を使って複数行の文字列から特定のパターンを検索する方法について教えてください。
  • 対象の文字列が複数行にわたっている場合でも、改行文字を削除することなく検索する方法を教えてください。
  • 正規表現の修飾子「s」や「m」を使っても一致させることができない場合、どのように対処すれば良いでしょうか?
回答を見る
  • ベストアンサー

PHPにおける正規表現について

PHPにおける正規表現について ご教授ください。 いわゆる、対象の文字列が複数行にわたっていた場合のことです。 $data = <<< EOF ABCDE FGH EOF; $hoge = preg_match("/EF/" ,$data,$match); と上記のようなコードがあった場合 対象の文字列群から【EF】という文字列を検索したい場合、どのように記述したら 【E(間に改行)F】の文字列と一致させる事ができるでしょうか? 仮に正規表現の修飾子の【s】や【m】を用いても上記の例の場合 一致させることができないと思います。 やはり、対象の文字列群 $data の改行文字をいったん削除したものから検索 するのがベターでしょうか? 正規表現に造詣の深い方よろしくご教授ください。

  • PHP
  • 回答数4
  • ありがとう数0

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

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

今後も需要ありそうなのでQiitaに分かりやすくまとめました。 http://qiita.com/mpyw/items/8dd5378cb01c877e1f7b >> 【地球連合軍】というキーワードを実行時にユーザー入力など動的に変化する文字列から一致させたい 一度空白文字を全て $text = preg_replace('/[\\s ]++/u', $text); ※全角スペースを文字クラスに入れているのでu修飾子が必須です などとして全て取り去ってしまうのが一番賢いかもしれません。 一応下記のように動的に正規表現を作ることも出来なくも無いですが・・・ $keyword = '地球連合軍'; $chars = preg_split('//u', $keyword, -1, PREG_SPLIT_NO_EMPTY); $quoted_chars = array_map(function ($i) { return preg_quote($i, '/');}, $chars); $pattern = '/' . implode('\\s*+', $quoted_chars) . '/'; ※マルチバイト文字列として分解するため、preg_splitではu修飾子が必須です ※この場合、$patternではu修飾子は不要です >> アスタリスクの後の+についてがちょっとわかりません。 Qiitaの記事を読んでもらえれば分かると思います。 >> 「\\」について、エスケープ不要である場合もある、・・・ まさにそういうことです! (正直PHP言語のこの実装気持ち悪いのであんまり好きじゃない) >> 本来PHPにおいて【¥s】というエスケープ文字は存在しませんよね ご指摘ありがとうございます・・・ どこで間違えたのやら、1年ぐらいずっと勘違いし続けていました・・・ \x20と間違えていたのかな・・・ (過去の回答訂正できるなら訂正したい) 心からご指摘感謝します m(_ _)m >> PHPは正規表現そのものを文字列で書くため はい、その認識で誤りはありません。 (\sが幻だったのが衝撃すぎて・・・ry

その他の回答 (3)

  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.4

「改行」だけマッチしたいなら\nやら\rをチェックした方がよいでしょう また改行を一つまで許すのか複数でもいいのかによっても若干書き方がちがいます <?PHP $data = <<< EOF ABXYCDX YEFX YGHX YIJ EOF; $pattern="/X(?:\r\n|\r|\n){0,1}Y/s"; preg_match_all($pattern,$data,$matches); print_r($matches); ?>

noname#244856
noname#244856
回答No.3

一部訂正 $keyword = '地球連合軍'; $chars = preg_split('//u', $keyword, -1, PREG_SPLIT_NO_EMPTY); $quoted_chars = array_map(function ($i) { return preg_quote($i, '/');}, $chars); $pattern = '/' . implode('[\\s ]*+', $quoted_chars) . '/u'; こっちのほうがいいかも。

noname#244856
noname#244856
回答No.1

$hoge = preg_match('/E\\s*+F/', $data, $matches); 一応こういうことも意識しておいてください。 http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q10110102910 http://okwave.jp/qa/q8199171.html

1000vicki
質問者

補足

ご回答ありがとうございます。 ご回答の様に、 たとえば、【地球連合軍】というキーワードを実行時にユーザー入力など動的に変化する文字列から一致させたいときは $hoge = preg_match('/地\\s*+球\\s*+連\\s*+合\\s*+軍/', $data, $matches); と、 [[どの文字のあとでも改行や空白があってもよい前提で正規表現をかかなきゃいけない]] んですね。 >>$hoge = preg_match('/E\\s*+F/', $data, $matches); とありますが、 【\\s*+】 上記、正規表現についてですが、このバックスラッシュ二つにはついては後に回すとして アスタリスクの後の+についてがちょっとわかりません。 これは正規表現上の空白類文字を表す【¥s】が0回以上【*】が一回以上【+】出現するという意味でよいでしょうか? また http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q10110102910 上記URLの >><個人的なお願い> 「\\」について、エスケープ不要である場合もある、 とありますがこれは例えば、 $toDay = "今日は、コンビニで¥3500円支払いました"; といった文字列を扱う場合、通常【¥3】というバックスラッシュのあと全角数字3に該当するエスケープ文字が 存在しない場合、事実上、バックスラッシュがそのまま¥と表記させる事例のことですよね? (※本来バックスラッシュ後0~7の半角数字がくると8進数形式のアスキー文字のようですが) 次に、 掲題の回答にありました 【\\s*+】 の部分ですが、 本来PHPにおいて【¥s】というエスケープ文字は存在しませんよね PHPマニュアルにおいても存在しないようですし、 実際にPHPのインタープリタで確認してみると >>> echo "文字列¥sテスト"; とうっても 出力されるものは #=> 文字列¥sテスト と表示されますが・・・。 上記と同様に http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q10110102910のページに記載している >><個人的なお願い> >>「PHPのためのエスケープ」と「正規表現エンジンのためのエスケープ」の両方を行う必要があります。 つまり「\」という文字自体を正規表現でマッチさせたければ「\\\\」とする必要があるのです。 とありますが、これはPHPのマニュアルにもどこかに記載があったとおもったのですが PHPは正規表現そのものを文字列で書くため 「PHPのためのエスケープ」これはPHPの文字列としての【¥¥¥¥】がエスケープシーケンスされて【¥¥】という文字が 「正規表現エンジン」へわたるという意味ですよね?正規表現そのものは文字列なので【¥¥】はエスケープされて 【¥】となると。これはつまりは正規表現エンジン内でも文字列としてあつかっているということですかね? ....この辺はPHPのCレベルの実装みないと正確にはりかいできないのですかね。

関連するQ&A

  • PHP5の正規表現でうまくマッチできない

    PHP5の正規表現で文字列中の独自タグをパースしようとしていて、 うまくいかず困り果てています。 正規表現パターンは、/<tag>.*<\/tag>/ 対象文字列は、<tag>こんにちは</tag><tag>こんばんは</tag> preg_match_all('/<tag>.*<\/tag>/', '<tag>こんにちは</tag><tag>こんばんは</tag>', $result) でマッチした文字列は、 $result[0]:<tag>こんにちは</tag> $result[1]:<tag>こんばんは</tag> となることを期待しているのですが、 実際は、 $result[0]:<tag>こんにちは</tag><tag>こんばんは</tag> となりました。 <tag>タグの間に入る文字列長、文字列フォーマットは不定です。 どうすれば期待通りの振る舞いに出来るでしょうか?

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

    /^R|ruby$/ 上記のような正規表現があったとします。 この正規表現の【|】の判断がわかりません。具体的には、/^ $/という記述から 対象の文字列の先頭がRかrのどちらかで以降がubyと続く文字列にマッチという 意味だと解釈しているのですが違うのでしょうか? 具体的にはRubyという文字列かrubyという文字列の二つのうちどちらかにしか マッチしないとおもっていたのですが、 rrubyという文字列やRrubyという文字列にもマッチします。そもそもこの場合のR|rの箇所ですが、これはRかrのどちらかが先頭にあり 二文字目からはubyという文字列がつづきますよ。という正規表現ではないのでしょうか? かなりこまっています。 識者のかたご教授ください。

  • PHP 正規表現

    はじめまして^^ 現在、PHPでプログラムを作っています。 そして、文字列の置き換えをする機会があり、 正規表現をつかうことになりました!! 置き換えに使う関数は、mb_ereg_replaceです! ある条件にあった部分の文字列を置き換えしたいと思っています。 そして、いろいろとやっていきましたら、あるひとつの壁にぶつかりました。。 例えば、PHPでは、正規表現の部分を [^文字]とやると、『文』と『字』という文字列以外にマッチという意味になるらしいのですが、 『文字』という文字列以外にマッチ、というふうに、表現したい場合は、 どう表現すればよいのですか? [^(文字)]とか、その他いろいろ、 自分なりに、色々ためしたのですが、うんともすんともいいません、、 どなたか、わかる方教えて下さいm(_ _)m

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

    正規表現を使って、文字列を抜き出したいのですがどうすればよいでしょうか? 対象となる文字列→<ここは文章>##あいうえお[1]:"test.jpg"##<ここは文章> 抜き出したい文字例→##あいうえお[1]:"test.jpg"## の##で囲まれた箇所です。 正規表現ど素人なため、どなたかご教授くださいm(_)m

    • ベストアンサー
    • PHP
  • 文字列を含まないという正規表現は?

    お世話になります。 例えば、文字「a」を含まないという正規表現は、 "[^a]" となりますが、文字列「abc」を含まないという正規表現はどうなりますでしょうか? "[^abc]" ではだめでしたし、 "[^(abc)]" でもだめでした。 また、改行などの制御文字を含めたどんな文字でもいいという正規表現はどうなりますでしょうか? ".*" では改行などが含まれるときはだめでした。 どうかご教授のほどよろしくお願い致します。 次のサイトは参考にしたサイトです。 正規表現の解説 目次 http://www4.ocn.ne.jp/~kaerume/k2e/regex_top.html#mnu_top

  • 正規表現について

    お世話になります。 ●●● ●●● という文字列かどうか判断する正規表現を作成したいです。 条件としては、 ・「文字1 (←全角スペース)文字2」という感じで、文字1と文字2に全角スペースが挟まれている感じで、文字列の先頭にも末尾にも空白文字は入ってはいけない(真ん中に1つのみ) ・文字1と文字2には、数字・空白以外の文字が入る(主に感じ・ひらがな・カタカナが入る)(文字数は一文字以上) といったところです。 自分で作成した正規表現は、 $pattern = '/^([\d\S])+ ([\d\S])+$/'; if( !preg_match($pattern,$chkStr) ) print "マッチしていない"; } なんですが、どうもマッチしてほしい文字にマッチしていないようなのです。 お手数ですがご教授ください。

    • ベストアンサー
    • PHP
  • 正規表現を教えてください。

    正規表現を教えてください。 C#で正規表現を用いた文字列検索を勉強中なのですが、うまくマッチさせることができません。教えていただけないでしょうか。 検索対象の文字列は下のようになります。 キーワード;値; 文字列中に該当するキーワードが存在する場合に、その値を取得するプログラムを考えています。しかし、私の正規表現では2つ目の「;」を検出してしまい、キーワードのみを取得することが出来ずに困っています。 見当違いの表記をしているとは思うのですがどなたかお助けください。 match = Regex.Match(line, "^(.*);"); C#初心者なものです。

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

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

    • 締切済み
    • PHP
  • 正規表現で一致しない(否定)場合の書き方

    正規表現で特定の文字列パターンに一致しない(否定)場合の書き方 ものすごく初歩的な質問なのですが、正規表現での否定の仕方がわかりません。 例えば、以下のように書いた場合は「第1回」や「第10回」などの文字列が一致しますが、 逆にこれらの条件に一致しないようにしたい場合はどのように記述すればよろしいのでしょうか? 第[1-9]+回

  • [15]にマッチする正規表現

    [15]にマッチする正規表現 [15] にマッチする正規表現を書きたいのですが、うまくいきません。。。。 簡単だ、と思ったのですが。。。 expr "$DATA1" : .*\[15\].* と書くと、中の数字が15じゃなくてもマッチしてしまいます。 expr "$DATA1" : .*15.* であれば"15"にマッチしますが、対象の文字列の都合上、カッコでも識別する必要があり 困っております。[と]をエスケープする目的で\をつける、と思っているのですが、何か 思い違いをしているのでしょうか。

専門家に質問してみよう