preg_match_all returns 仅每秒匹配一次

preg_match_all returns only every second match

我有这样的程序:

$txt = "
{ABC}
+ 1
- 1

{DEF}
+ 2
- 2

{IJK}
+ 3
- 3

{LMN}
+ 4 
- 4
";
preg_match_all('/\{.*?\{/s', $txt, $matches);
var_dump($matches);

我想匹配两个左大括号(或文本结尾)之间的所有内容。 但是我的结果只包含 ABC 和 IJK 块,因为下一个 { 已经吃完了。

array(1) {
  [0]=>
  array(2) {
    [0]=>
    string(16) "{ABC}
+ 1
- 1

{"
    [1]=>
    string(16) "{IJK}
+ 3
- 3

{"
  }
}

使用正则表达式 lookahead (?=) 运算符将允许您匹配 { 之前的任何内容,而无需实际匹配 { 字符本身。

preg_match_all('/\{.*?(?=\{)/s', $txt, $matches)

会给你这个结果:

array(1) {
  [0]=>
  array(3) {
    [0]=>
    string(15) "{ABC}
+ 1
- 1

"
    [1]=>
    string(15) "{DEF}
+ 2
- 2

"
    [2]=>
    string(15) "{IJK}
+ 3
- 3

"
  }
}

您提到您还想匹配 { 和文本末尾之间的内容。您可以通过在前瞻中使用 pipe | operator and the end of string anchor $ 来做到这一点。

preg_match_all('/\{.*?(?=\{|$)/s', $txt, $matches)

会给你想要的结果:

array(1) {
  [0]=>
  array(4) {
    [0]=>
    string(15) "{ABC}
+ 1
- 1

"
    [1]=>
    string(15) "{DEF}
+ 2
- 2

"
    [2]=>
    string(15) "{IJK}
+ 3
- 3

"
    [3]=>
    string(14) "{LMN}
+ 4 
- 4"
  }
}

我建议使用 negated character class [^ 匹配除左括号外的任何字符。

这样它会从开头 { 匹配到下一次出现 { 或字符串结尾。

{[^{]*

Regex demo | Php demo

例如

preg_match_all('/{[^{]*/', $txt, $matches);