preg_match字符串中的可选元素

时间:2011-05-27 09:19:18

标签: string preg-match design-patterns optional

我有两个字符串,最多包含3个元素:

1) anychar[price]{alphanum} e.g. a1\')[=00.00]{a1234}
2) anychar:anychar{alphanum} e.g. a1\'):a2\'){a1234}

...但{}元素是可选的,可能并不总是存在。我分别编写了以下模式:

1)/(.+)\[(.+)\]\{*(\w+)*\}*/ - 按预期工作

2)/(.+)\:(.+)\{*(\w+)*\}*/ - 如果移除了{}元素,则可以正常工作,但不能使用它。

2的结果数组如下:

( [0] => a1\'):a2\'){a123} [1] => a1\') [2] => a2\'){a123} )

我尝试过以上几种不同的排列,但没有骰子。有什么想法吗?

1 个答案:

答案 0 :(得分:1)

首先你应该在{,}和(\ w +)之后删除*。

'/(.+)\:(.+)\{(\w+)\}/'

给出

array(4) {
  [0]=>
  string(18) "a1\'):a2\'){a1234}"
  [1]=>
  string(5) "a1\')"
  [2]=>
  string(5) "a2\')"
  [3]=>
  string(5) "a1234"
}

*表示0,1或几个,并且PCRE试图找到它可以的最快路线,所以如果你把整个第三部分作为可选(通过使用*无处不在),那么最快的路线是将所有内容都包含在第二部分中分组并跳过第三个,这就是你的代码不起作用的原因。

现在为了处理第三部分是可选的这一事实,你必须使用一个积极的前瞻:在第二组中,你将要求pcre选择它,只有它可以匹配它之后的另一个正则表达式。最终的正则表达式是:

'/(.+)\:(.+(?=(?:(?<=[^}])$|\{(\w+)\})))/'

我改变的是:

  • 在第二组中,我在表单中添加了一个正向前瞻(?= regex)。如上所述,这意味着它必须匹配。默认情况下,Lookahead不具有选择性,这意味着它们不会在最终结果中创建条目/它们不会返回给您。

  • 在前瞻中,我创建了两个案例,这意味着为了匹配,第二组的。+必须匹配我前瞻的任何一个案例。

  • 第一种情况非常基本,它意味着字符串的结尾没有前面的},当第3部分不存在时,这将匹配字符串

  • 第二种情况如果你选择了第3组,我们可以选择它以便在结果中返回