前回の質問で解決したはずなのですが、仕変のため、再度質問させてください。
次のフォーマットで文字列を抽出したいと思います。
●フォーマット
任意の文字列
[pat_A]任意の文字列A
[pat_B]任意の文字列B
●抜き出したい文字列
任意の文字列A
任意の文字列B
●特記事項
[pat_A]よりも前に任意の文字列が含まれる場合があります。
任意の文字列には、改行コード(\n\r)が含まれる場合があります。
任意の文字列Aは、[pat_A]~[pat_B]まで
任意の文字列Bは、[pat_B]~eofまで
これを正規表現で実現しようといろいろ試したのですが、なぜか改行が含まれません。
preg_match_all('/(\[pat_A|pat_B\])(.*|\n|\r)/', $msg, $n);
preg_match_all('/(\[pat_A|pat_B\])(.*|.*\n.*|.*\r.*)/', $msg, $n);
●例
$msg = "aaa
bbbbb
[pat_A]
cccc
[pat_B]dd
ee
fff";
●上記正規表現を実行した結果
1) pat_Aで抽出された文字列
なし
2) pat_Bで抽出された文字列
dd
●期待値
1) pat_Aで抽出したい文字列
cccc
2) pat_Bで抽出したい文字列
dd
ee
fff
[pat_A][pat_B]は出現順序が変わる可能性があるので、
strPosなどで文字列操作するより、できる限り正規表現を使いたいのです。
方法についてご教授をお願いいたします。
コメント欄が開いてないので、本回答で失礼しますと共に、
回答1は浅はかでした。申し訳ない。
改行を含む文字列であり、順不同、
さらに、特定の文字による判断が無理となれば、
一発では無理かと思いますので、下記提案します。
// パターン $pat = '/(\[pat_A\]|\[pat_B\])/'; // 分割してデータ部分取り出し $m = preg_split($pat, $msg); array_shift($m); // キー項目の取り出しと結合 preg_match_all($pat, $msg, $n); $n[1] = $m; // 結果出力 print_r($n);
preg_match_all('/(\[pat_A\]|\[pat_B\])(\r\n|\r|\n)?([^\[]+)/', $msg, $n);
もしくは
preg_match_all('/(\[pat_A\]|\[pat_B\])([^\[]+)/', $msg, $n);
上記の違いは[pat_A]や[pat_B]直後の改行を消し去るかどうかの違いです。
http://q.hatena.ne.jp/ダミーで失礼します。
早速のご回答ありがとうございます。
なるほど、パターン区切り文字を次のパターンの"["としたわけですね。
ただ、これだと任意の文字列AかBの中に"["が含まれるとうまく動きません。
[^ ]だと文字列ではなく、1文字が含まれないとしか判断できません。
区切りを次の文字列[pattern_A]か[pattern_B]とすることはできないでしょうか?
パターン修飾子を使い、以下のようにするのが正解です。
パターンAは $n[1] に、パターンBは $n[2] に代入されます。
preg_match("/\[pat_A\]([^\[pat_B\]]*)\[pat_B\](.*$)/ms", $msg, $n);
http://jp2.php.net/manual/ja/reference.pcre.pattern.modifiers.ph...
ご回答ありがとうございます。
なるほど、やはりこうなりますよね。理解しました。
わがままをいわせていただくと、[pat_A]と[pat_B]の順序が入れ替わるというのはだめですよね^^;
ありがとうございました。
コメント欄が開いてないので、本回答で失礼しますと共に、
回答1は浅はかでした。申し訳ない。
改行を含む文字列であり、順不同、
さらに、特定の文字による判断が無理となれば、
一発では無理かと思いますので、下記提案します。
// パターン $pat = '/(\[pat_A\]|\[pat_B\])/'; // 分割してデータ部分取り出し $m = preg_split($pat, $msg); array_shift($m); // キー項目の取り出しと結合 preg_match_all($pat, $msg, $n); $n[1] = $m; // 結果出力 print_r($n);
ご回答いただきありがとうございます。
この方法は気がつきませんでした。すごくいい方法だと思います。
すごくわがままなのですが、もう1つ質問させていただいてよろしいでしょうか?
仮に[pat_A][pat_B]が$msgに複数含まれる場合、foreachでカウントするより、
一発でそのマッチ数を知る方法はないでしょうか?
よろしくお願いいたします!
>[pat_A][pat_B]が$msgに複数含まれる場合、foreachでカウントするより、
>一発でそのマッチ数
回答3の方法では、複数の[pat_A]や[pat_B]の存在を容認しているため、
続けて下記コマンドを実行すれば、それぞれの個数を得られます。
// 要素の内容毎に集計 $c = array_count_values($n[0]); // 結果出力 print_r($c);
PHP: array_count_values - Manual
※この程度ならコメント欄でかまいませんよ。
そのほうが多分レスポンス早くなりますし・・・。
遅くにご回答ありがとうございます。
本当に助かりました。ありがとうございました。
# コメント欄!?そうですね。ご配慮くださりありがとうございました。
ご回答いただきありがとうございます。
この方法は気がつきませんでした。すごくいい方法だと思います。
すごくわがままなのですが、もう1つ質問させていただいてよろしいでしょうか?
仮に[pat_A][pat_B]が$msgに複数含まれる場合、foreachでカウントするより、
一発でそのマッチ数を知る方法はないでしょうか?
よろしくお願いいたします!