2013-08-12 49 views
0

我有一个带正则表达式的小代码片段,用于匹配数值,然后是矩形括号内的可选文本,以字符'A'结尾。一个例子是我的正则表达式应该匹配3次,但只匹配两次(PHP)

preg_match_all("/([0-9]+)(?:\[(.*)\])?A/", "123[SomeText]A345[SomeOtherText]A678A", $matches); 
print_r($matches); 

和预期的结果是有三场比赛:

Array 
(
    [0] => Array 
     (
      [0] => 123[SomeText]A 
      [1] => 345[SomeOtherText]A 
      [2] => 678A 
     ) 

    [1] => Array 
     (
      [0] => 123 
      [1] => 345 
      [2] => 678 
     ) 

    [2] => Array 
     (
      [0] => SomeText 
      [1] => SomeOtherText 
      [2] => 
     ) 
) 

,而上面的代码只匹配了两次:

Array 
(
    [0] => Array 
     (
      [0] => 123[SomeText]A345[SomeOtherText]A 
      [1] => 678A 
     ) 

    [1] => Array 
     (
      [0] => 123 
      [1] => 678 
     ) 

    [2] => Array 
     (
      [0] => SomeText]A345[SomeOtherText 
      [1] => 
     ) 
) 

我看不到我在做什么错在给定的正则表达式中。任何修复正则表达式的建议都是值得欢迎的。

回答

3

你的问题是greediness。量词(如.*)尽可能地消耗。而且由于.也可以匹配]它刚好超过第一个收盘]到最后一个。你可以通过使用.*?来重复不合格(匹配尽可能少)。但在你的情况下有一个更好的(更快)选项。确保,你不能走过去的收盘],从允许的字符将其取出:

/([0-9]+)(?:\[([^\]]*)\])?A/ 

Working demo.

注意,你实际上没有逃脱右括号,因为它是在班上第一个字符(且因为空类是不允许的,你不需要逃吧) - 另一种是类外,所以它不可能是一个右括号之一:

/([0-9]+)(?:\[([^]]*)])?A/ 

Working demo.

你喜欢哪个变种是一个口味问题,我会说。

+0

我认为这可能与“贪婪”,但我不知道如何/在哪里考虑。非常感谢您的回答。 – Alex

+0

不仅是一个正确的答案,而且需要额外的正则表达式理解水平,才能真正实现快速,准确的解决方案。 +1 – ridgerunner

0

这种模式怎么样? 。

\d+(\[.*?\])?A 
2

的*是贪婪的,所以改变它:

<?php 
preg_match_all("/([0-9]+)(?:\[([^A]*)\])?A/", "123[SomeText]A345[SomeOtherText]A678A", $matches); 
print_r($matches); 

试试看:http://3v4l.org/BZgmH

0

好吧,如果你很确定你的文本不包含“A”字符,那么这应该工作:

'/(\d*)([^A]*)/' 

但如果每个部分与已在开始了一些新部件结束这应该工作:

'/(\d*)([^\d]*)/' 

这一行

preg_match_all('/(\d*)([^\d]*)/', "123[SomeText]A345[SomeOtherText]A678A", $matches, PREG_SET_ORDER); 
print_r($matches);