为了账号安全,请及时绑定邮箱和手机立即绑定

用递归和正则表达式替换字符串中的文本

用递归和正则表达式替换字符串中的文本

PHP
互换的青春 2021-10-22 14:12:10
在浏览器中显示输出之前,我使用标签来替换文本,类似于 Wordpress 的短代码。示例字符串: Hi, this is a block of text {{block:welcome}} and this is a system variable {{variable:system_version}}我有相应的函数来替换这些块,并且我意识到 foreach 或 while 函数将是处理它的最佳方法,但不幸的是,替换一个{{...}}可能会引入另一个。因此,我选择递归,直到找不到更多。典型的递归只有一次,但我有两个合二为一的场景。也许调用该函数 3 次会起作用,但听起来“错误”。现在这就是问题发生的地方:我不想在它们出现时更换它们:1) A page where the URL you are calling contains something 2) Any form element such as `<input>` or `<textarea>`.我需要关于如何通过正则表达式从上面的 #2 中排除的帮助。我的正则表达式目前看起来像这样:(^\{\{((?!keep).)*$我意识到它可能仍然是错误的,或者需要修改 - 还不太有效)。如果项目包含“保持”,例如,{{block:welcome:keep}}它不应该被替换,但是当这样做时,递归永远不会停止,因为我一直在寻找要替换的项目,从而耗尽内存,或者获得最大的嵌套级别错误。我之所以要这样做,是因为我不希望在 ADMIN 页面上或在编辑表单内容时替换内容。有人愿意给它一个裂缝吗?如果这很重要,我正在使用 PHP。谢谢!编辑 1由于@Pablo 的答案是在聊天中给我的,我决定编辑我的问题以反映为什么他的答案被标记为正确的答案。我的正则表达式现在看起来像这样: /(?:<(?:textarea|select)[\s\S]*?>[\s\S]*?)?({{variable:(.*?)}})[\s\S]*?(?:<\/(?:textarea|select)>)?|(?:<(?:input)[\s\S]*?)?{{variable:(.*?)}}(?:[\s\S]*?>)?/im然后我检查匹配项是否包含输入、选择或文本区域,如果是,则{{暂时用其他内容替换,然后进行替换,完成后,将“其他内容”更改回{{Pablo 建议的内容。我的正则表达式要感谢这个问题的答案:文本替换:PHP/regex。如果以上编辑不属于,请随意删除。
查看完整描述

1 回答

?
海绵宝宝撒

TA贡献1809条经验 获得超8个赞

我建议不要寻找完美的 RegEx,而是考虑使用preg_replace_callback()。它应该允许您使用更简单的 RegEx,同时更好地控制模板引擎的搜索和替换算法。考虑以下示例:

  1. resolvePlaceholder() 生成替换内容

  2. interpolate()解析模板字符串。它支持多达 4 级的嵌套解析。

  3. 停止递归解析以 开头的标签!

<?php


function resolvePlaceholder($name)

{

    $store = [

        'user:first'              => 'John',

        'user:last'               => 'Doe',

        'user:full_name'          => '{{user:first}} {{user:last}}',

        'block:welcome'           => 'Welcome {{user:full_name}}',

        'variable:system_version' => '2019.1',

        'nest-test'               => '{{level1}}',

        'level1'                  => '{{level2}}',

        'level2'                  => '{{level3}}',

        'level3'                  => '{{level4}}',

        'level4'                  => '{{level5}}',

        'level5'                  => 'Nesting Limit Test Failed',

        'user-template'           => 'This is a user template with {{weird-placeholder}} that will not be replaced in edit mode {{user:first}}',

    ];


    return $store[$name] ?? '';

}


function interpolate($text, $level = 1)

{

    // Limit interpolation recursion

    if ($level > 5) {

        return $text;

    }


    // Replace placeholders

    return preg_replace_callback('/{{([^}]*)}}/', function ($match) use ($level) {

        list($tag, $name) = $match;

        // Do not replace tags with :keep

        if (strpos($name, ':keep')) {

            // Remove :keep?

            return $tag;

        }


        if (strpos($name, '!') === 0) {

            return resolvePlaceholder(trim($name, '!'));

        }


        return interpolate(resolvePlaceholder($name), $level + 1);

    }, $text);

}


$sample = 'Hi, this is a block of text {{block:welcome}} and this is a system variable {{variable:system_version}}. ' .

    'This is a placeholder {{variable:web_url:keep}}. Nest value test {{nest-test}}. User Template: {{!user-template}}';


echo interpolate($sample);

// Hi, this is a block of text Welcome John Doe and this is a system variable 2019.1. This is a placeholder {{variable:web_url:keep}}. Nest value test {{level5}}. User Template: This is a user template with {{weird-placeholder}} that will not be replaced in edit mode {{user:first}}



查看完整回答
反对 回复 2021-10-22
  • 1 回答
  • 0 关注
  • 125 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号