【问题标题】:Find text inside curly braces and replace text including curly braces查找大括号内的文本并替换包括大括号的文本
【发布时间】:2019-03-10 15:12:40
【问题描述】:

我想找到一个模式{text} 并替换包含大括号的文本。

$data = 'you will have a {text and text} in such a format to do {code and code}';
$data= preg_replace_callback('/(?<={{)[^}]*(?=}})/', array($this, 'special_functions'),$data);

和我的special function 包含回调代码以完全替换大括号和有条件的文本。

public function special_functions($occurances){
        $replace_html = '';
        if($occurances){
            switch ($occurances[0]) {
                case 'text and text':
                    $replace_html = 'NOTEPAD';
                    break;
                case 'code and code':
                    $replace_html = 'PHP';
                    break;

                default:
                    $replace_html ='';
                    break;
            }
        }
        return $replace_html;
    }

预期输出

你会有一个这样格式的记事本来做 PHP

如何在 php 中使用正则表达式同时使用 preg_replace_callback 替换文本和花括号

【问题讨论】:

  • special_functions 代码添加到问题中并提供预期结果。
  • 预期输出是什么?
  • @revo 更新了我的问题
  • @WiktorStribiżew 我已将功能添加到我的问题中
  • 请看下面我的回答,它一定对你有用。如果没有,请提供一个更新的 PHP fiddle 来显示问题。

标签: php regex preg-replace-callback


【解决方案1】:

您需要像这样编辑模式:

$data = preg_replace_callback('/{{([^{}]*)}}/', array($this, 'special_functions'), $data);

{{([^{}]*)}} 模式将匹配:

  • {{ - {{ 子字符串
  • ([^{}]*) - 第 1 组:除 {} 之外的任何 0+ 个字符
  • }} - }} 文字

然后,在special_functions 函数中,将switch ($occurances[0]) 替换为switch ($occurances[1])$occurrances[1] 是使用 ([^{}]*) 模式捕获的文本部分。由于整个匹配是{{...}},捕获的是...... 用于检查 switch 块中的可能情况,并且大括号将被删除,因为它们使用( = 添加到由preg_replace_callback 函数替换的匹配值中)。

请参阅PHP demo

【讨论】:

  • 那行得通。我有个疑问。 $occurances[0] 包含带大括号的文本,$occurances[1] 包含不带大括号的文本。所以逻辑上 $occurances[0] 应该替换文本和大括号?
  • @Shadow $occurances[0] 不会取代任何东西。那是与preg_replace_callback 函数匹配的文本,因此它将被替换的文本。
  • 我投了赞成票。也总是会替换 [1] 索引中的内容。对吗?
  • @Shadow 是的,但是当{{...}} 中的文本包含{} 时,[^{}]* 会阻止任何匹配。如果需要,请将[^{}]* 替换为.*?
  • @Shadow 好的,这没那么重要,从模式中删除一个{}'/{([^{}]*)}/',当然,没有火箭科学:)
【解决方案2】:

如果你有这么复杂的正则表达式,你可能想看看T-Regx

$data = 'you will have a {text and text} in such a format to do {code and code}';

pattern('{{([^{}]*)}}')
  ->replace($data)
  ->first()
  ->callback(function (Match $match) {
      switch ($match->group(1)) {
          case 'text and text':
              return 'NOTEPAD';

          case 'code and code':
              return 'PHP';

          default:
              return '';
      }
  });

【讨论】: