регулярное выражение между 2 строками - PullRequest
2 голосов
/ 13 сентября 2011

Например, у меня есть текст

a1aabca2aa3adefa4a

Я хочу извлечь 2 и 3 с регулярным выражением между abc и def, поэтому 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 ]

5 голосов
/ 13 сентября 2011
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];

работает на вашем примере. Предполагается, что в вашей строке ровно один экземпляр abc и def на строку.

Причина, по которой ваша попытка не сработала, заключается в том, что ваша группа захвата (\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
0 голосов
/ 03 декабря 2011

Вы спрашиваете, возможно ли это с одним 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)
...