【问题标题】:substr values don't match preg_match_all PREG_PATTERN_ORDERsubstr 值与 preg_match_all PREG_PATTERN_ORDER 不匹配
【发布时间】:2012-12-12 21:15:06
【问题描述】:

我使用 preg_match_all 的PREG_PATTERN_ORDER 来返回在字符串中找到的值中的位置。然后当尝试substr,引用他们回来时,他们不会排队。我预计会有一个偏移量,但似乎每个案例都有未确定的错位。

这是因为 preg_match_all 返回的是字节而不是字符吗?如果是这样,有没有办法将字节转换为字符?如果我完全不合时宜,我可以发布一些代码......

好的,这是适用的代码:

// RETURN POSITION OF START AND END TAGS TO ARRAY
function getTagPositions($strBody, $start, $end)
{
    preg_match_all('/' . preg_quote($start, '/') . '([\w\s.]*?)'. preg_quote($end, '/').'/im', $strBody, $strTag, PREG_PATTERN_ORDER);
    $intOffset = 0;
    $intIndex = 0;
    $intTagPositions = array();

    foreach($strTag[0] as $strFullTag) {
        $intTagPositions[$intIndex] = array('start' => (strpos($strBody, $strFullTag, $intOffset)), 'end' => (strpos($strBody, $strFullTag, $intOffset) + strlen($strFullTag)));
        $intOffset += strlen($strFullTag);
        $intIndex++;
    }
    return $intTagPositions;
}

function arrayValRecursive($key, array $arr){
    $val = array();
    array_walk_recursive($arr, function($v, $k) use($key, &$val){
        if($k == $key) array_push($val, $v);
    });
    return count($val) > 1 ? $val : array_pop($val);
}

$arrayOfPositions = getTagPositions($html,$go,$stop);
$arrayOfStart = arrayValRecursive('start', $arrayOfPositions);   //print_r($arrayOfStart);
$arrayOfEnd = arrayValRecursive('end', $arrayOfPositions);   //print_r($arrayOfEnd);

  $offset = 0;
  $range = $arrayOfStart[$i] + $offset;
  $rangeEnd = $arrayOfEnd[$i];    
  echo '<br>'.$range.' to '.$rangeEnd.' is: <br>'; 
  echo substr($html, $range, $rangeEnd); 

【问题讨论】:

  • preg_match_all "返回完整模式匹配的数量(可能为零),如果发生错误,则返回 FALSE。"看来您使用此功能不正确。

标签: php preg-match-all substr


【解决方案1】:

根据preg_match_all

返回值
返回完整模式匹配的数量(可能为零),如果发生错误,则返回 FALSE。

如果你想得到字符串的偏移量,使用PREG_OFFSET_CAPTURE

PREG_OFFSET_CAPTURE
如果这个标志被传递,对于每一个出现的匹配,附加的字符串偏移量也将被返回。请注意,这会将匹配项的值更改为一个数组,其中每个元素都是一个数组,该数组由偏移量 0 处的匹配字符串及其在偏移量 1 处的字符串偏移量组成。

这是一个例子:

$count = preg_match_all('/\S+/', 'Hello, world!', $matches, PREG_OFFSET_CAPTURE);
echo "count=$count\n";
var_dump($matches);

这作为输出给出

count=2
array(1) {
  [0]=>
  array(2) {
    [0]=>
    array(2) {
      [0]=>
      string(6) "Hello,"
      [1]=>
      int(0)
    }
    [1]=>
    array(2) {
      [0]=>
      string(6) "world!"
      [1]=>
      int(7)
    }
  }
}

您可以看到模式匹配$count=2 次。它匹配位置$matches[0][0][1]=0 的“Hello”,并且匹配“world!”。在位置$matches[0][1][1]=7

下面是你如何遍历所有匹配项

$start = array();
$end = array();
foreach($matches[0] as $match) {
    $start[] = $match[1];
    $end[] = $match[1] + strlen($match[0]);
}

【讨论】:

  • 在使用PREG_OFFSET_CAPTURE 寻找解决方案后,我在php.net 上找到了getTagPositions 函数。您能否演示如何在此函数中使用PREG_OFFSET_CAPTURE?谢谢。
  • @John 查看更新后的答案。这应该让您了解$matchesPREG_OFFSET_CAPTURE 的结构。
  • 谢谢。到目前为止,我有这个:function arrayPositions($string, $start, $end){ $count = preg_match_all('/' . preg_quote($start, '/') . '([\w\s.]*?)'. preg_quote($end, '/').'/im', $string, $matches, PREG_OFFSET_CAPTURE); //echo "count=$count\n"; //var_dump($matches); } 如何获得所有“开始”值和另一个“结束”值的数组。通过将您的示例合并到函数中,它会破坏 arrayValRecursive 函数。
  • @John 起始值已经存在,正如我在示例中所写的那样。对于结束偏移,您可以获取开始偏移并添加匹配长度:$start = $matches[0][0][1]; $end = $start + strlen($matches[0][0][0]);
  • @John 是的,这只是第一个。看我回答的结尾。我补充说,如何获得所有开始和结束偏移量。
猜你喜欢
  • 2011-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-03
  • 2011-03-17
  • 2011-10-18
  • 1970-01-01
相关资源
最近更新 更多