2013-03-26 2 views
3

Я пытаюсь перевести скрипт javascript в PHP. До сих пор идет хорошо, но я наткнулся на некоторый код на который я невежественный:Javascript lastIndex свойство regex для PHP regex

while (match = someRegex.exec(text)) { 
    m = match[0]; 

    if (m === "-") { 

     var lastIndex = someRegex.lastIndex, 
      nextToken = someRegex.exec(parts.content); 

     if (nextToken) { 
       ... 
     } 

     someRegex.lastIndex = lastIndex; 
    } 
} 

Переменная someRegex выглядит следующим образом:

/[^\\-]+|-|\\(?:[0-3][0-7]{0,2}|[4-7][0-7]?|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}|c[A-Za-z]|[\S\s]?)/g 

Exec должно быть эквивалентно preg_match_all в PHP:

preg_match_all($someRegex, $text, $match); 
$match = $match[0]; // I get the same results so it works 

foreach($match as $m){ 

    if($m === '-'){ 

    // here I don't know how to handle lastIndex and the 2nd exec :(

    } 

} 
+0

Где 'parts' приходят из в JavaScript? –

+0

Это объект с несколькими свойствами, который построен с другим регулярным выражением. В PHP я сделал его ассоциативным массивом (он выглядит одинаково) – Alex

ответ

3

Я не использовал бы это lastIndex магии вообще - вы выполняете регулярное выражение дважды по каждому индексу. Если вы действительно хотите это сделать, вам нужно установить флаг PREG_OFFSET_CAPTURE в preg_match_all, чтобы вы могли получить позицию, добавить длину захвата и использовать ее в качестве следующего смещения preg_match.

Лучше использовать что-то вроде этого:

preg_match_all($someRegex, $text, $match); 
$match = $match[0]; // get all matches (no groups) 

$len = count($match); 
foreach($match as $i=>$m){ 

    if ($m === '-') { 
     if ($i+1 < $len) { 
      $nextToken = $match[$i+1]; 
      … 
     } 
     … 
    } 
    … 
} 
1

Фактически, exec не эквивалентен preg_match_all, так как exec останавливается в первом совпадении (модификатор g только устанавливает значение lastIndex для прокрутки строки). Это эквивалентно preg_match. Итак, вы найдете первое совпадение, получите значение благодаря аргументу $ array, смещению этого значения (содержится в $ flags) и продолжите поиск, установив смещение (последний аргумент).

Я предполагаю, что второе исполнение не будет проблемой, так как вы будете делать то же самое, что и в версии javascript.

Обратите внимание, что я не пробовал цикл, но это должно быть довольно просто, как только вы выяснили, как preg_match работает именно с необязательными аргументами (я запустил некоторый тест).

$lastIndex = 0; 
while(preg_match($someRegex, $text, $match, PREG_OFFSET_CAPTURE, $lastIndex) { 
    $m = $match[0][0]; 
    $lastIndex = $match[0][1] + strlen($m); //thanks Bergi for the correction 

    if($m === '-') { 
      // assuming the $otherText relate to the parts.content thing 
    if(preg_match($someRegex, $otherText, $secondMatch, 0, $lastIndex)) { 
     $nextToken = $secondMatch[0]; 
     ... 
    } 
    } 
} 

Я думаю, что это должно быть (извините, за небольшую ошибку, не сделали php на некоторое время).

+2

'exec' сам по себе эквивалентен' preg_match', но он используется в цикле while, поэтому он по существу эквивалентен 'preg_match_all'. – Vulcan

+0

Это если вы забыли ** nextToken = someRegex.exec (parts.content); **. У него/нее будет более легкий цикл времени с preg_match. Кроме того, ему, возможно, потребуется выполнить второй матч сразу после первого. – Loamhoof

+0

Разве это не '$ lastIndex = $ match [0] [1] + strlen ($ m);'? – Bergi