/ /なぜこの正規表現がPHPでは貪欲ではない - php、regex、preg-replace-callback

なぜこの正規表現はPHPで貪欲ではありません - php、regex、preg-replace-callback

この正規表現はMarkdownのようにリストと一致するはずです。

/((?:(?:(?:^[+*-] )(?:[^rn]+))(?:r|n?))+)/m

Javascriptで動作します( g フラグを追加しましたが、PHPへの移植に問題があります。それは貪欲なふるまいをしません。これが私のサンプルコードです:

$string = preg_replace_callback("`((?:(?:(?:^* )(?:[^rn]+))(?:r|n?))+)`m", array(&$this, "bullet_list"), $string);

function bullet_list($matches) { var_dump($matches) }

3行のリストをフィードすると、これが表示されます。

array(2) { [0]=> string(6) "* one " [1]=> string(6) "* one " } array(2) { [0]=> string(6) "* two " [1]=> string(6) "* two " } array(2) { [0]=> string(8) "* three " [1]=> string(8) "* three " }

どうやら var_dump 一度ではなく三度呼ばれている正規表現は貪欲であり、できるだけ多くの行と一致しなければならないので、私はそれから期待するように。私はregex101.comでそれをテストしました。 正しく機能させるにはどうすればよいですか。

回答:

回答№1は1

この正規表現は正しく動作しません。 rn 入力テキストの改行

一部 (?:r|n?) マッチ どちらかr またはnしかし、両方ではありません。 (regex101は改行を以下のように扱います。 n ただ、それでそれはそこで働きます)。

以下は機能しますか?

/(?:(?:(?:^[+*-] )(?:[^rn]+))[rn]*)+/m

(または、不要な非キャプチャグループをすべて削除した後 - ありがとう@ M42!)

/(?:^[+*-] [^rn]+[rn]*)+/m

回答№2の場合は3

正規表現は次のように減らすことができます。

(?:^[+*-] [^rn]+R*)+

これらのグループをすべて実行する必要はありません。
R あらゆる種類の改行を意味します n または r または rn

編集: R 文字クラスにおけるその特別な意味を失います。 [R] 手段 R
HamZaに感謝します


回答№3の場合は1

箇条書きのない最初の行に達するまで、これはすべての箇条書きの行に一致します。

(?<=^|R)*[sS]+?(?=$|R[^*])
  • * 箇条書きに一致します。
    • (?<=^|R) 文字列の先頭または改行が前に付きます。
  • [s|S]+? 欲張らずに任意の文字にマッチ
    • (?=$|R[^*]) 一致したシーケンスの後には、文字列または改行文字とそれに続く*。基本的に、これは、行頭以外の行が見つかったとき、または文字列の終わりになったときに、シーケンスの一致が完了したことを意味します。

結果:

結果の一致は、下のRegexBuddy出力に表示されます(Regex 101はそれを処理できません)。

正規表現結果