2013-03-26 167 views
3

我試圖在PHP中翻譯JavaScript腳本。到目前爲止,會好的,但我碰到一些代碼上我無言以對跌跌撞撞:Javascript lastIndex正則表達式屬性到PHP正則表達式

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 

高管應相當於在PHP中preg_match_all:

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的? – 2013-03-26 14:58:13

+0

這是一個由另一個正則表達式構建的一些屬性的對象。在PHP中,我將它作爲一個關聯數組(它看起來一樣) – Alex 2013-03-26 15:01:31

回答

3

我根本不會使用那個lastIndex魔法 - 本質上你是在每個索引上執行兩次正則表達式。如果你真的想這樣做,你需要設置PREG_OFFSET_CAPTURE標誌preg_match_all,這樣你可以獲得位置,添加捕捉長度並將其用作下一個偏移量。

更好地利用這樣的:

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 2013-03-26 15:19:26

+0

這是如果你忘記** nextToken = someRegex.exec(parts.content); **。他/她用preg_match可以更容易地進行循環。此外,他/她可能需要在第一場比賽之後進行第二場比賽。 – Loamhoof 2013-03-26 15:24:53

+0

是不是'$ lastIndex = $ match [0] [1] + strlen($ m);'? – Bergi 2013-03-26 15:45:46