【问题标题】:How do I process the largest match first in PHP?如何在 PHP 中首先处理最大的匹配项?
【发布时间】:2010-03-22 06:33:30
【问题描述】:

好的,所以我尝试先搜索一下,但我不知道如何措辞这个问题或搜索短语。让我解释一下。

我的数据如下所示:

<!-- data:start -->
    <!-- 0:start -->
        <!-- 0:start -->0,9<!-- 0:stop -->
        <!-- 1:start -->0,0<!-- 1:stop -->
        <!-- 2:start -->9,0<!-- 2:stop -->
        <!-- 3:start -->9,9<!-- 3:stop -->
        <!-- 4:start -->0,9<!-- 4:stop -->
    <!-- 0:stop -->
    <!-- 1:start -->
        <!-- 0:start -->1,5<!-- 0:stop -->
        <!-- 1:start -->1,6<!-- 1:stop -->
        <!-- 2:start -->3,6<!-- 2:stop -->
        <!-- 3:start -->3,8<!-- 3:stop -->
        <!-- 4:start -->4,8<!-- 4:stop -->
    <!-- 1:stop -->
    <!-- 2:start -->
        <!-- 0:start -->0,7<!-- 0:stop -->
        <!-- 1:start -->1,7<!-- 1:stop -->
    <!-- 2:stop -->
<!-- data:stop -->

所以它基本上是一堆点。这是我目前用来尝试解析它的代码,以便它可以创建一个像这样的数组:

Array (
    0 => Array (
        0 => "0,9",
        1 => "0,0",
        2 => "9,0",
        3 => "9,9",
        4 => "0,9"
    ),
    1 => Array (
        0 => "1,5",
        1 => "1,6",
        2 => "3,6",
        3 => "3,8",
        4 => "4,8"
    ),
    2 => Array (
        0 => "0,7",
        1 => "1,7"
    )
)

但是,它返回的数组如下所示:

Array (
    0 => "0,9",
    1 => "0,0",
    2 => "9,0"
)

查看我屏幕上的较大数组,您会发现它在匹配时设置了该变量的第一个实例。那么我如何让它首先找到最广泛的匹配然后处理内部。这是我目前正在使用的功能:

function explosion($text) {
    $number = preg_match_all("/(<!-- ([\w]+):start -->)\n?(.*?)\n?(<!-- \\2:stop -->)/s", $text, $matches, PREG_SET_ORDER);
    if ($number == 0) return $text;
    else unset($item);
    foreach ($matches as $item) if (empty($data[$item[2]])) $data[$item[2]] = $this->explosion($item[3]);
    return $data;
}

我确信这将是我忽略的一些愚蠢和简单的事情,但我想这对你来说只是一个简单的答案。

编辑:这是我从中提取此样本的整个数据集的full output log。标签被打印出来(用 > 和 <code></code> 元素内,以便于阅读。

这是搞砸的部分:

Array ( [0] => <!-- 0:start --> <!-- 0:start -->0,9<!-- 0:stop -->  [1] => 0 [2] => <!-- 0:start -->0,9 )

0 => <!-- 0:start -->0,9

所以它在第一次出现停止标记时停止其中的另一块。我是否应该考虑相反的方向并首先处理最小的部分,替换它们以免中断较大的部分,然后再处理较大的部分?

【问题讨论】:

  • 为什么不使用 JSON 而不是这种奇怪的格式?

标签: php regex parsing preg-match-all


【解决方案1】:

给你:

function explosion($text) {
    preg_match_all("/<!-- ([\d]+):start -->(.+?)<!-- .*:stop -->/", $text, $matches, PREG_SET_ORDER);

    $return = array();
    foreach($matches as $match) {
        if($match[1]==0) {
            $return[] = array();
        }
        $return[count($return)-1][] = $match[2];
    }   
    return $return;
}

【讨论】:

  • 我不明白这在更大的模型中如何工作?如果它与标签内的 0 匹配,那不会只捕获数组吗?我在问题中添加了一个日志,也许它会有所帮助。
  • 这个想法是您不必费心匹配外部标签,只需匹配内部标签。每当开始标签中的数字为0 时,您就知道外部标签一定已更改,因此您为下一批结果创建另一个数组。
【解决方案2】:

这对我有用:

function explosion($text) {
    $number = preg_match_all('/<(.*?)>(.+?)[<]/s', $text, $matches);
    if ($number == 0) return $text;

    $temp = array();
    $data = array();
    foreach($matches[2] as $coords){
        if(trim($coords)==""){
            if(!empty($temp)){
                $data[] = $temp;
                $temp = array();
            }
        }else{
            $temp[] = $coords;
        }
    }
    return $data;
}

您的代码的问题在于它拾取了子标签和标记值。当然在浏览器中打印时它会被隐藏,因此请尝试记录它以进行调试。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-25
    • 1970-01-01
    • 1970-01-01
    • 2019-10-14
    • 1970-01-01
    • 2019-10-18
    • 1970-01-01
    相关资源
    最近更新 更多