2013-03-26 166 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