【问题标题】:preg_replace string with arraypreg_replace 字符串与数组
【发布时间】:2013-03-06 15:39:39
【问题描述】:

好的,所以我的问题很简单。我希望答案也是。 假设我有以下 php 字符串:

<!DOCTYPE html>
<html>
<head>
    <title>test file</title>
</head>
<body>
    <div id="dynamicContent">
        <myTag>PART_ONE</myTag>
        <myTag>PART_TWO </myTag>
        <myTag> PART_THREE</myTag>
        <myTag> PART_FOUR </myTag>
    </div>
</body>
</html>

假设这是 $content。 现在,您可以看到我有 4 个自定义标签 (myTag),其中包含一个单词的内容。 (PART_ONE、PART_TWO 等) 我想用 4 个不同的字符串替换这 4 个。后面的 4 个字符串在一个数组中:

$replace = array("PartOne", "PartTwo", "PartThree", "PartFour");

我这样做了,但没有成功:

$content = preg_replace("/<myTag>(.*?)<\/myTag>/s", $replace, $content);

所以,我想搜索 myTags(它找到 4 个)并将其替换为数组的一个条目。第一次出现应该用 $replace[0] 替换,第二次应该用 $replace[1] 替换,等等。 然后,它将“新”内容作为字符串(而不是数组)返回,以便我可以使用它进行进一步解析。

我应该如何意识到这一点?

【问题讨论】:

  • 搜索 PART_ONE 等会简单得多...
  • 哦,是的,我忘了说我不知道​​ myTag 的值,所以 PART_ONE 也可以是“MY_ELEPHANT”。我应该能够在 html 模板中输入任何内容,然后代码将看到 myTag 标记之间的任何内容。另外,我不认为“你不能用正则表达式解析 html”这句话在这里适用,因为我不是在解析标签的属性,而只是在解析标签的值,这对于正则表达式来说是一个简单且故障安全的任务。
  • 你可以使用 preg_replace_callback() 代替。

标签: php regex parsing


【解决方案1】:

类似下面的东西应该可以工作:

$replace = array("PartOne", "PartTwo", "PartThree", "PartFour");
if (preg_match_all("/(<myTag>)(.*?)(<\/myTag>)/s", $content, $matches)) {
    for ($i = 0; $i < count($matches[0]); $i++) {
        $content = str_replace($matches[0][$i], $matches[1][$i] . $replace[$i] . $matches[3][$i], $content);
    }
}

【讨论】:

    【解决方案2】:

    一种方法是循环遍历要替换的数组中的每个元素;将myTag 替换为myDoneTag 或您完成的每个单词,这样您就可以找到下一个单词。然后你总是可以在最后放回myTag,你就有了你的字符串:

    for(ii=0; ii<4; ii++) {
        $content = preg_replace("/<myTag>.*<\/myTag>/s", "<myDoneTag>".$replace[ii]."<\/myDoneTag>", $content, 1);
    }
    $content = preg_replace("/myDoneTag/s", "myTag", $content);
    

    【讨论】:

    • 如果正则表达式匹配,它将第一次替换所有内容,而不关心其他 3 次循环迭代。
    • 嗯,虽然我已经认为这样的事情会是答案并接受它,但我认为使用它并不明智,因为它基本上是一个循环中的一个循环(preg_replace 循环也是),因此这滞后于性能。我想如果没有其他高性能解决方案,我只会使用 (X)HTML 解析或类似的东西。
    • @h2ooooooo - 你是对的。添加了“limit”参数并将其设置为1 - “仅替换第一个实例”。
    • @JohnSmith - 我相信清晰度应该胜过速度,除非性能真的很重要。您将围绕此循环四次 - 正则表达式将在每次找到第一个匹配项时停止。你真的认为你会受到可衡量的性能损失吗?
    【解决方案3】:

    使用正则表达式,您可以这样做:

    $replaces = array('foo','bar','foz','bax');
    $callback = function($match) use ($replaces) {
            static $counter = 0;
            $return = $replaces[$counter % count($replaces)];
            $counter++;
            return $return;
    };
    var_dump(preg_replace_callback('/a/',$callback, 'a a a a a '));
    

    但实际上,在 html 或 xml 中搜索标签时,您需要一个解析器:

    $html = '<!DOCTYPE html>
    <html>
    <head>
        <title>test file</title>
    </head>
    <body>
        <div id="dynamicContent">
            <myTag>PART_ONE</myTag>
            <myTag>PART_TWO </myTag>
            <myTag> PART_THREE</myTag>
            <myTag> PART_FOUR </myTag>
        </div>
    </body>
    </html>';
    
    $d = new DOMDocument();
    $d->loadHTML($html);
    $counter = 0;
    foreach($d->getElementsByTagName('mytag') as $node){
            $node->nodeValue = $replaces[$counter++ % count($replaces)];
    }
    echo $d->saveHTML();
    

    【讨论】:

      【解决方案4】:

      这应该是您要查找的语法:

      $patterns = array('/PART_ONE/', '/PART_TWO/', '/PART_THREE/', '/PART_FOUR/');
      $replaces = array('part one', 'part two', 'part three', 'part four');
      
      preg_replace($patterns, $replaces, $text);
      

      但请注意,这些是按顺序运行的,因此如果“PART_ONE”的文本包含随后将被替换的文本“PART_TWO”。

      【讨论】:

      • 源数据中标签的内容未知
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-05-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-15
      • 1970-01-01
      • 2016-03-22
      相关资源
      最近更新 更多