正则表达式匹配2个字符串

时间:2011-09-13 12:04:49

标签: php regex match preg-match-all

例如我有文字

a1aabca2aa3adefa4a

我想在 abc和def之间使用正则表达式提取2和3,因此结果中不应包含1和4。

我试过这个

if(preg_match_all('#abc(?:a(\d)a)+def#is', file_get_contents('test.txt'), $m, PREG_SET_ORDER))
  print_r($m);

我明白了

> Array
(
    [0] => Array
        (
            [0] => abca1aa2adef
            [1] => 3
        )

)

但我想要这个

Array
(
    [0] => Array
        (
            [0] => abca1aa2adef
            [1] => 2
            [2] => 3
        )

)

这可以通过一个 preg_match_all调用吗?我该怎么办?

由于

2 个答案:

答案 0 :(得分:5)

preg_match_all(
    '/\d       # match a digit
    (?=.*def)  # only if followed by <anything> + def
    (?!.*abc)  # and not followed by <anything> + abc
    /x', 
    $subject, $result, PREG_PATTERN_ORDER);
$result = $result[0];

适用于您的示例。它假设您的字符串中每行只有一个abcdef的实例。

您尝试不起作用的原因是与该数字匹配的捕获组(\d)位于另一个重复的组(?:a(\d)a)+中。每次重复,捕获的结果都会被覆盖。这就是正则表达式的工作原理。

换句话说 - 看看比赛期间发生了什么:

Current position    Current part of regex    Capturing group 1
--------------------------------------------------------------
a1a                 no match, advancing...   undefined
   abc              abc                      undefined
      a2a           (?:a(\d)a)               2
         a3a        (?:a(\d)a) (repeated)    3 (overwrites 2)
            def     def                      3

答案 1 :(得分:0)

您询问是否可以使用单个preg_match_all。

确实如此。 此代码完全输出您想要的内容。

<?php
$subject='a1aabca2aa3adefa4a';
$pattern='/abc(?:a(\d)a+(\d)a)def/m';
preg_match_all($pattern, $subject, $all_matches,PREG_OFFSET_CAPTURE | PREG_PATTERN_ORDER);
$res[0]=$all_matches[0][0][0];
$res[1]=$all_matches[1][0][0];
$res[2]=$all_matches[2][0][0];
var_dump($res);
?>

这是输出:

array
0 => string 'abca2aa3adef' (length=12)
1 => string '2' (length=1)
2 => string '3' (length=1)