可变大小的前瞻消耗

时间:2017-07-27 07:06:40

标签: php regex regex-lookarounds

我试图使用正则表达式来解析使用php的变量字符串,例如,该字符串可以是;

"twoX // threeY"

"twoX /// threeY"

所以有一个左关键字,divider包含2或3个斜杠和一个右关键字。这些也是我想单独使用的部分。

"/((?<left>.+)?)(?=(?<divider>[\/]{2,3}))([\/]{2,3})((?<right>.+)?)/";

当我在第一个字符串上使用这个正则表达式时,所有内容都被正确解析,所以;

  

:twoX

     

分隔符://

     

正确:threeY

但是当我在第二个字符串上运行此表达式时, left divider 无法正确解析。我得到的结果是;

  

:twoX /

     

分隔符://

     

正确:threeY

我使用正则表达式中的 {2,3} 为分隔符选择2或3个斜杠。但这种方式似乎并不适用于匹配所有人物。

有没有办法让正则表达式解析2或3个斜杠而不重复整个序列?

2 个答案:

答案 0 :(得分:4)

(.+)?是一个贪婪的点匹配模式,匹配尽可能多的字符,其中1为最小值。因此,由于下一个模式只需要2个字符,因此只有2个字符将被捕获到下一个组中,第一个/将属于第1组。

在第一组中使用 lazy 模式:

'~(?<left>.*?)(?<divider>/{2,3})(?<right>.*)~'
          ^^^

请参阅regex demo。在模式周围添加^$锚点,以便在必要时匹配整个字符串。

请注意,您不需要在前瞻和消费模式部分重复相同的模式,只会使模式变得麻烦,(?=(?<divider>[\/]{2,3}))([\/]{2,3}) = (?<divider>[\/]{2,3})

<强>详情

  • (?<left>.*?) - 小组&#34;离开&#34;匹配除了换行符之外的任何0+字符,尽可能
  • (?<divider>/{2,3}) - 2或3个斜杠(自~用作正则表达式分隔符后无需转义)
  • (?<right>.*) - Group&#34; right&#34;将除了换行符之外的任何0+字符匹配为尽可能很多(直到行尾)。

更加天真的分裂方法,请参阅PHP demo

$s = "twoX // threeY";
print_r(preg_split('~\s*(/{2,3})\s*~', $s, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY));
// => Array ( [0] => twoX [1] => // [2] => threeY )

您丢失了名称,但可以在以后的步骤中添加它们。

答案 1 :(得分:2)

默认情况下+量词是贪婪的,这意味着它会尝试匹配尽可能多的字符。所以你想让第一个+懒惰,所以它不会尝试匹配第一个/,通过添加?量词,你可以使+懒惰:{{1 }}。
这将导致以下正则表达式:

+?