正则表达式匹配除2个连续花括号之外的任何内容

时间:2010-12-23 18:03:51

标签: php regex pcre

除了2个连续花括号({)之外,还有什么是正则表达式? 示例字符串:
{{some text}} string I want {{another set {{and inner}} }}
我只想获得string i want

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

提前致谢

2 个答案:

答案 0 :(得分:6)

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

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

测试程序

<?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) ""

答案 1 :(得分:2)

如果你需要做一些更复杂的内容,比如处理内容或变量,那么你可以使用递归正则表达式,利用(?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:<abcde(1:<fg(0:<hi>)jk>)lm>)


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

正面和背面的双括号与任何目标组件匹配,大括号的内容是两个定义选项中的一个或多个:

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

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

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