【问题标题】:How to loop through, match and replace?如何循环、匹配和替换?
【发布时间】:2023-10-12 22:18:02
【问题描述】:

我有多个带有相同花括号的字符串我想将它们替换为动态如果我得到计数​​为 1 然后需要替换第一次出现,如果计数为 2 然后替换第二次出现,依此类推,直到条件满足。

<?php

include_once("con.php");
$db = new Da();

$con = $db->con();

$String = "{{ONE}} {{TWO}} {{THREE}} {{FOUR}} {{FIVE}} {{SIX}}";

 $Count = 1;
 if(preg_match_all("/\{\{[^{}]+\}\}/", $lclString, $matches)) {

    foreach ($matches[0] as $match) {
        $Count++;
        $Query = "SELECT link FROM student WHERE linkVal = '".$match."'";
        $Result = $con->query($Query);

        if($row = $Result->fetch(PDO::FETCH_ASSOC)) {

            $NewValue = preg_replace("/\{\{[^{}]+\}\}/", $row["link"], $String);

        }
    }

        echo json_encode($NewValue);

 } 


?>

如果第一次出现 {{ONE}} 应该用 $row["link"] 替换新值, 其次将 {{TWO}} 替换为新值,依此类推。

【问题讨论】:

  • 怎么样:$NewValue = str_replace($match, $row["link"], $String);
  • 会检查你的建议
  • 那只替换了一场比赛。
  • 在循环中使用它,而不是preg_replace
  • 我想知道你是否可以使用 preg_replace_callback() like this demo 的东西。不知道我是否理解你的问题:p

标签: php regex preg-replace preg-match-all regex-group


【解决方案1】:

在每场比赛的循环中,我建议你不要使用preg_replace,而是使用str_replace

if(preg_match_all("/\{\{[^{}]+\}\}/", $lclString, $matches)) {
    $NewValue = $String;
    foreach ($matches[0] as $match) {
        $Count++;
        $Query = "SELECT link FROM student WHERE linkVal = '".$match."'";
        $Result = $con->query($Query);

        if($row = $Result->fetch(PDO::FETCH_ASSOC)) {
            $NewValue = str_replace($match, $row["link"], $NewValue);
            //          ^^^^^^^^^^^^^^^^^^
        }
    }
    echo json_encode($NewValue);
} 

【讨论】:

  • 除了使用str_replace - 不确定这和我的答案是否有任何区别。
  • @Michael:echo json_encode($NewValue); 的输出是什么,你期待什么?
  • @NigelRen:当然,这是唯一的区别,我在发布之前评论了这个问题作为答案,这就是我在你之后 2 分钟发布的原因。
  • 但是您的评论包含关于在原始字符串中不断替换的原始缺陷。
  • @NigelRen:我专注于正确替换的方式,然后在回答时修复了一些错误,str_replacepreg_replace 效率更高
【解决方案2】:

您可以通过在一个查询中获取所有替换值来大大简化您的代码:

$String = "{{ONE}} {{TWO}} {{THREE}} {{FOUR}} {{FIVE}} {{SIX}}";
if(preg_match_all("/\{\{[^{}]+\}\}/", $String, $matches)) {
    $Query = "SELECT linkVal, link FROM student WHERE linkVal IN('".implode("','", $matches[0])."')";
    $Result = $con->query($Query);
    if ($rows = $Result->fetchAll(PDO::FETCH_ASSOC)) {
        $NewValue = str_replace(array_column($rows, 'linkVal'), array_column($rows, 'link'), $String);
    }
    echo json_encode($NewValue);
} 

【讨论】:

  • @Michael 你知道查询是否返回任何结果吗?可以var_dump($rows);吗?
  • 查询返回多个不同的结果
  • @Michael 如果查询返回结果,str_replace 应该可以工作 - 这是一个示例:3v4l.org/ch9HV
  • @Michael 抱歉,我刚刚意识到我在代码中有错字。你能再试一次吗(我已经编辑了答案)
  • @Michael 你能告诉我你用var_dump($rows); 得到了什么吗?如果我能看到,我确信我可以快速解决问题。
【解决方案3】:

您的代码存在一些问题,您需要确保preg_match_all() 中的变量是您尝试搜索的字符串。

但主要问题在于更换部件。您需要替换当前匹配值 ($match) 并将其替换为新字符串 - 目前您始终替换原始字符串中的新匹配。在这里,我从原始字符串创建 $NewValue 并继续替换其中的值...

if(preg_match_all("/\{\{[^{}]+\}\}/", $String, $matches)) {
    $NewValue = $String;
    foreach ($matches[0] as $match) {
        $Count++;
        $Query = "SELECT link FROM student WHERE linkVal = '".$match."'";
        $Result = $con->query($Query);

        if($row = $Result->fetch(PDO::FETCH_ASSOC)) {
            $NewValue = preg_replace("/".preg_quote($match)."/", 
                              $row["link"], $NewValue);
        }
    }

    echo json_encode($NewValue);

}

您还应该考虑使用准备好的语句,因为目前您可能会遇到 SQL 注入问题。

【讨论】:

  • 只发生了一次替换。
  • 用相同的替换替换两个字符串,例如 {{ONE}} {{TWO}} 替换为 1 和 1。
  • 你能在student 表上显示linkVallink 的值吗? (因为$match 的值将是{{ONE}}
【解决方案4】:

我们可能希望在这里设计的表达式可以是以下之一:

({{)(.+?)(}})

仅使用捕获组()

DEMO 1


(?:{{)(.+?)(?:}})

如果我们不想保留{{}},在这里我们可以使用非捕获组(?:)

DEMO 2

然后,我们可以简单地做我们想做的preg_replace

测试

$re = '/(?:{{)(.+?)(?:}})/m';
$str = '{{ONE}} {{TWO}} {{THREE}} {{FOUR}} {{FIVE}} {{SIX}}';
$subst = '$1';

$result = preg_replace($re, $subst, $str);

echo "The result of the substitution is ".$result;

【讨论】:

    【解决方案5】:

    您可以使用preg_replace_callback 来遍历您的匹配项。

    例如

    $str = "{{ONE}} {{TWO}} {{THREE}} {{FOUR}} {{FIVE}} {{SIX}}";
    $replaced = preg_replace_callback('/{{([^{}]*)}}/', function($match) {
    // $match[1] contains the current match (first capture group) e.g. ONE
    // return your replacement for the current match, e.g. reversed string ENO
    return strrev($match[1]);
    }, $str);
    echo $replaced;
    

    输出将是ENO OWT EERHT RUOF EVIF XIS

    【讨论】: