PHP正则表达式 - 匹配多种可能性(管道)

时间:2014-03-22 21:04:35

标签: php regex preg-match-all preg-replace-callback

我想从文本中的多个URL中获取所有ID(整数)。这些网址可能如下所示:

http://url.tld/index.php/p1
http://url.tld/p2#abc
http://url.tld/index.php/Page/3-xxx
http://url.tld/Page/4

为此,我构建了两个正则表达式(URL由URL bbcode包围):

\[url\](http\://url\.tld/index\.php/p(\d+).*?\)[/url\]
\[url\](http\://url\.tld(?:/index\.php)?/Page/(\d+).*?\)[/url\]

但是,如果我对每个正则表达式执行preg_match_all,我会得到一个看起来像这样的数组(哪个是正确的):

array(3) {
  [0]=>
  array(2) {
    [0]=>
    string(62) "[url]http://url.tld/index.php/Page/6-fdgfh/[/url]"
    [1]=>
    string(50) "[url]http://url.tld/Page/7[/url]"
  }
  [1]=>
  array(2) {
    [0]=>
    string(51) "http://url.tld/index.php/Page/6-fdgfh/"
    [1]=>
    string(39) "http://url.tld/Page/7"
  }
  [2]=>
  array(2) {
    [0]=>
    string(1) "6"
    [1]=>
    string(1) "7"
  }
}

但是,如果我将两个正则表达式与管道结合起来:

\[url\](http\://url\.tld/index\.php/p(\d+).*?|http\://url\.tld(?:/index\.php)?/Page/(\d+).*?)\[/url\]

它构建一个这样的数组(这是错误的):

array(4) {
  [0]=>
  array(3) {
    [0]=>
    string(71) "[url]http://url.tld/index.php/p9-abc#hashtag[/url]"
    [1]=>
    string(62) "[url]http://url.tld/index.php/Page/6-fdgfh/[/url]"
    [2]=>
    string(50) "[url]http://url.tld/Page/7[/url]"
  }
  [1]=>
  array(3) {
    [0]=>
    string(60) "http://url.tld/index.php/t9-abc#hashtag"
    [1]=>
    string(51) "http://url.tld/index.php/Page/6-fdgfh/"
    [2]=>
    string(39) "http://url.tld/Page/7"
  }
  [2]=>
  array(3) {
    [0]=>
    string(1) "9"
    [1]=>
    string(0) ""
    [2]=>
    string(0) ""
  }
  [3]=>
  array(3) {
    [0]=>
    string(0) ""
    [1]=>
    string(1) "6"
    [2]=>
    string(1) "7"
  }
}

====

所以,我的问题是:我该如何解决这个问题?我需要的是第一个例子中的数组结构,同时使用正则表达式作为一个正则表达式,因为我需要一个一致的结构来稍后执行preg_replace_callback

1 个答案:

答案 0 :(得分:1)

我认为您正在寻找Branch Reset group

\[url]((?|http://url\.tld/index\.php/p(\d+).*?|http://url\.tld(?:/index\.php)?/Page/(\d+).*?))\[/url]

或者,对于我们中间受到线路噪音挑战的人:

\[url]
(
  (?|
    http://url\.tld/index\.php/p(\d+)[^[]*
  |
    http://url\.tld(?:/index\.php)?/Page/(\d+)[^[]*
  )
)
\[/url]

这会捕获组#2中的数字,无论正则表达式的哪个部分与之匹配。整个URL仍然在组#1中捕获。