【问题标题】:Regular expression to match anything but 2 consecutive curly braces正则表达式匹配除 2 个连续花括号外的任何内容
【发布时间】:2011-05-30 02:33:59
【问题描述】:

除了 2 个连续的大括号 ({) 之外,匹配任何内容的正则表达式是什么?
示例字符串:
{{some text}} string I want {{another set {{and inner}} }}
我只想得到string i want

使用堆栈来做这些事情已经超出了我的想法,但我想知道这是否可以使用正则表达式来完成。
我正在使用 PHP 的 PCRE

提前致谢

【问题讨论】:

  • {{ unbalanced {{ braces }} 的预期结果是什么?
  • 假设没有不平衡的大括号。

标签: php regex pcre


【解决方案1】:

如果您需要对内容做一些更复杂的事情,例如处理内容或变量,那么您可以使用递归正则表达式,利用 (?R) 运算符。

$data = "{{abcde{{fg{{hi}}jk}}lm}}";
$regexp = "#\{\{((?:[^(\{\{)(\}\})]+|(?R))+)\}\}#";
$count = 0;

function revMatch($matches) {
  global $regexp, $count;

  if (is_array($matches)) {
    // Match detected, process for nested components
    $subData = preg_replace_callback($regexp, 'revMatch', $matches[1]);
  } else {
    // No match, leave text alone
    $subData = $matches;
  }

  // This numbers each match, to demonstrate call order
  return "(" . $count++ . ":<" . $subData . ">)";
}

echo preg_replace_callback($regexp, 'revMatch', $data);

这会将{{abcde{{fg{{hi}}jk}}lm}} 转换为(2:&lt;abcde(1:&lt;fg(0:&lt;hi&gt;)jk&gt;)lm&gt;)


关于正则表达式的一点解释:#\{\{((?:[^(\{\{)(\}\})]+|(?R))+)\}\}#

前后双大括号匹配任意目标组件,大括号内容为定义的两个选项中的一个或多个:

  1. 没有双括号的字符串[^(\{\{)(\}\})]+

  2. 整个正则表达式重复。 (?:) 括号是非捕获组。

注意。 #s 是模式分隔符,我认为额外的斜杠会进一步降低可读性。

【讨论】:

    【解决方案2】:

    使用前瞻断言(?!{{|}}) 来验证您的外部集合中没有嵌套的大括号集。

    {{((?!{{|}}).)*}}
    

    测试程序

    <?php
    $string = '{{lot {{of}} characters}}';
    
    for (;;)
    {
        var_dump($string);
        $replacement = preg_replace('/{{((?!{{|}}).)*}}/', '', $string);
    
        if ($string == $replacement)
            break;
    
        $string = $replacement;
    }
    

    输出

    string(25) "{{lot {{of}} characters}}"
    string(19) "{{lot  characters}}"
    string(0) ""
    

    它似乎也可以合理地处理各种边缘情况:

    # Unbalanced braces.
    string(23) "{{lot {{of}} characters"
    string(17) "{{lot  characters"
    
    string(23) "lot {{of}} characters}}"
    string(17) "lot  characters}}"
    
    # Multiple sets of braces.
    string(25) "{{lot }}of{{ characters}}"
    string(2) "of"
    
    # Lone curlies.
    string(41) "{{lot {{of {single curly} }} characters}}"
    string(19) "{{lot  characters}}"
    string(0) ""
    

    【讨论】:

    • 我从未听说过的for(;;)魔法是什么?
    • @metro - 这是while (true)的另一种写作方式。
    猜你喜欢
    • 2012-01-21
    • 1970-01-01
    • 1970-01-01
    • 2018-04-04
    • 1970-01-01
    • 2021-01-23
    • 2016-01-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多