由于重复捕获组而不是捕获重复组,正则表达式不匹配

时间:2016-08-25 21:48:29

标签: php regex

我有以下正则表达式:

/(?:[\[\{]*)(?:([A-G\-][^A-G\]\}]*)+)(?:[\]\}]*)/

使用以下表达式:

{A''BsCb}

我预计会有3个匹配的结果

A''
Bs
Cb

但是https://regex101.com/的测试只给了我最后一个匹配Cb,并告诉我重复捕获组只捕获最后一次迭代,将捕获组放在重复的组周围。

我以为那就是我做的!我以为我已经理解了这里描述的问题http://www.regular-expressions.info/captureall.html 因此我的+以外的括号内有捕获组。

但是要么已经太晚了,或者我需要有人在提到regexp时不会崩溃,以告诉我哪里出错了。

3 个答案:

答案 0 :(得分:2)

您可以使用{0}的public struct STATUSSTRUCT { public UInt64 nameLen; [MarshalAs(UnmanagedType.LPStr, SizeConst = 4128)] public StringBuilder name; } status = new STATUSSTRUCT(); status.nameLen = 4128; status.name = new StringBuilder(4128); getStatus(ref status); 格式获取此模式:

preg_match_all

demo

答案 1 :(得分:1)

您正在尝试匹配重复捕获组并获取捕获。 PHP PCRE正则表达式无法实现。

您可以做的是确保提取所有{...} / [...]子字符串,从括号中修剪它们并使用简单的[A-G-][^A-G]*正则表达式,或者添加{{1运算符并使你的正则表达式不可维护,但作为原始正则表达式。

解决方案1 ​​

\G

请参阅regex demo。注意:此正则表达式不会检查结束/(?:[[{]*|(?!\A)\G)\K[A-G-][^A-G\]}]*/ ],但可以添加前瞻性。

  • } - 匹配(?:[[{]*|(?!\A)\G)[,零个或多个发生,或上一次成功匹配的结束位置
  • { - 省略了目前为止匹配的文字
  • \K - 来自[A-G-]AG
  • 的信件
  • - - 除[^A-G\]}]*A以外的其他字符,且不包括G]

请参阅PHP demo

解决方案2

}

请参阅PHP demo

$re = '/(?|{([^}]*)}|\[([^]]*)])/'; $str = "{A''BsCb}"; $res = array(); preg_match_all($re, $str, $m); foreach ($m[1] as $match) { preg_match_all('~[A-G-][^A-G]*~', $match, $tmp); $res = array_merge($tmp, $res); } print_r($res); 正则表达式只匹配(?|{([^}]*)}|\[([^]]*)]){...}(但不是[...]{...])等字符串,并将括号内的内容捕获到第1组(由于分支重置组[...}重置每个分支中的组ID)。然后,我们所需要的只是通过一个更连贯的(?|...)正则表达式来获取我们需要的东西。

答案 2 :(得分:1)

你已经明白了。关于@ sln的评论,没有办法在一个或不同的捕获组中收集每个单一匹配,同时在PCRE中重复一个组,这是PHP的正则表达式。在这种情况下,只捕获最后一个匹配。

但是,如果声明字符串应该位于字符串的开头和结尾并不重要,那么您只需要这些值就可以做更少的工作:

$array = array_filter(preg_split("~(?=[A-G])~", trim("{A''BsCb}", '[{}]')));

正则表达式:

(?=[A-G]) # Positive lookahead to find next character be one from character class

此正则表达式将匹配所有类似的位置,以在分割时输出正确的数据:

array(3) {
  [1]=>
  string(3) "A''"
  [2]=>
  string(2) "Bs"
  [3]=>
  string(2) "Cb"
}

Live demo