【问题标题】:PHP - How to avoid replacing a replacement stringPHP - 如何避免替换替换字符串
【发布时间】:2019-05-11 17:45:15
【问题描述】:

我正在编写一个脚本,该脚本允许学生将他们的答案输入到表单中,并就他们的答案提供即时反馈。

我从一个字符串 ($content) 开始,其中包含完整的任务,方括号中有空格,如下所示:

There's [somebody] in the room. There isn't [anybody] in the room. Is [anybody] in the room?

现在脚本识别解决方案(某人、任何人、任何人)并将它们保存在一个数组中。学生的答案也在一个数组中。

要查看答案是否正确,脚本会检查 $input[$i] 和 $solution[$i] 是否相同。

现在问题来了:我希望脚本用输入框替换占位符,其中解决方案错误,绿色解决方案正确。然后,此更新版本的 $content 将显示在下一页上。 但是如果有两个相同的解决方案,这会导致多次替换,因为替换被再次替换......

我尝试将 preg_replace 限制为 1,但这也不起作用,因为它不会跳过已被替换的解决方案。

$i=0; 而($解决方案[$i]){ //回答正确 if($solution[$i] == $input[$i]){ //替换占位符>绿色解决方案 $content = str_replace($solution[$i], $solution_green[$i], $content); } //回答错误 别的{ //替换占位符>输入框重试 $content = str_replace($solution[$i], $solution_box[$i], $content); } $i++; } 打印$内容; //根据学生的回答输出新表格

有什么办法可以避免更换替代品吗?

我希望我没有过多地闲逛......多年来一直在为这个问题绞尽脑汁,如果有任何建议,我将不胜感激。

【问题讨论】:

    标签: php string replace


    【解决方案1】:

    我解决这个问题的方法是将原始内容拆分为与文本中的标记相关的段。那么你explode()]的原文,你最终得到...

    Array
    (
        [0] => There's [somebody
        [1] =>  in the room. There isn't [anybody
        [2] =>  in the room.
    Is [anybody
        [3] =>  in the room?
    )
    

    如您所见,每个数组元素现在都对应于答案/解决方案编号。因此,在替换文本时,它会改为 $parts[$i]。同样作为一种保障措施,它取代了[text 以确保还有其他解决方案,但这应该可以完成工作。

    最后,代码使用implode() 重建原始内容并使用] 将其添加回来。

    $parts = explode("]", $content);
    $i=0;
    
    while (isset($solution[$i])){
        //answer correct
        if($solution[$i] == $input[$i]){
            //replace placeholder > green solution
            $parts[$i] = str_replace("[".$solution[$i], "[".$solution_green[$i], $parts[$i]);
        }
        //answer wrong
        else{
            //replace placeholder > input box to try again
            $parts[$i] = str_replace("[".$solution[$i], "[".$solution_box[$i], $parts[$i]);
        }
        $i++;
    }
    $content = implode( "]", $parts);
    

    【讨论】:

    • 非常感谢您抽出宝贵时间帮助我!奇迹般有效。 :)
    【解决方案2】:

    您可以使用sprintf()/vsrpintf() 函数来替换位置占位符,但首先您必须为其准备句型。每个“解决方案占位符”都应该替换为%s,以便以后sprintf()可以将每个替换为相应的字符串。

    你可以在循环中这样做:

    $fields = [];
    while (isset($solution[$i])) {
        $fields[] = ($solution[$i] === $input[$i])
            ? $solution_green[$i]
            : $solution_box[$i];
    
        //doesn't matter if you replace more than one here
        $content = str_replace($solution[$i], '%s', $content);
        $i++;
    }
    
    print vsprintf($content, $fields);
    //or for php>=5.6: sprintf($content, ...$fields);
    

    这是对当前代码状态的简单修复解决方案。它可能会被重构(解析正确单词时的模式替换,绿色/盒子数组可能会被替换为生成您需要的字符串的方法......等等)

    【讨论】:

    • 感谢您的建议!作为一个相对初学者,我还不熟悉 sprintf 和 vsprintf。会读一读。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多