具有多个{}块的表达式

时间:2012-04-30 11:00:59

标签: php regex

我正在尝试创建一个匹配任何这些文本的正则表达式:

#{text}
#{text1}{text2}
#{text1}{numbers}{text2}
#{text1}{text with spaces}{numbers}{text2}

等等。基本上第一个块只能保存没有空格的文本,但其余的可以容纳任何东西。在那之后,得到那些text1 ...数字等匹配我一直在尝试一些正则表达式,但它没有成功。这是最后一个:

/#{(\w+)}({([\ a-zA-Z0-9*])})*/U

提前致谢!

编辑:就像@stema建议的那样,我将正则表达式更改为了这个:

/#\{(\w+)\}(\{([^}]*)\})*/

我避开了Ungreedy标志,因为它根本没有帮助表达:)。但是,结果并不像我需要的那么多:

array(4) {
  [0]=>
  string(42) "#{text1}{text with spaces}{numbers}{text2}"
  [1]=>
  string(5) "text1"
  [2]=>
  string(7) "{text2}"
  [3]=>
  string(5) "text2"
}

似乎没有解析inbetween参数(这对我来说很奇怪)。

2 个答案:

答案 0 :(得分:5)

我看到的主要问题是量词是错位的

/#{(\w+)}({([\ a-zA-Z0-9*])})*/U
                        ^

应该在字符类之外

/#{(\w+)}({([\ a-zA-Z0-9]*)})*/U

如果以下大括号中的内容可能不是您可以执行的操作

/#\{(\w+)\}(\{([^}]*)\})*/U

[^}]是一个否定的字符类,它匹配除了结束的大括号之外的任何内容。

我也逃脱了花括号,因为它们作为量词的一部分具有特殊含义。有些语言在没有形成这样的量词时会按字面意思匹配,但为了清楚起见,当它们匹配时,最好总是逃避它们。

<强>更新

您可以将其中一个群组设为非捕获群组,因为您似乎不需要它

/#\{(\w+)\}(?:\{([^}]*)\})*/

这应该给你这个结果

array(4) {
  [0]=>
  string(42) "#{text1}{text with spaces}{numbers}{text2}"
  [1]=>
  string(5) "text1"
  [2]=>
  string(5) "text2"
}

但您始终只会获得结果数组中重复组的最后一个匹配项,因为每个匹配项都存储在array[2]。第二场比赛将覆盖第一场比赛,第三场比赛将覆盖第二场......

您可以做的是使用正则表达式进行格式验证,然后进行拆分,例如像这样的东西

$in = "#{text1}{text with spaces}{numbers}{text2}";
$result = preg_split('/}{|#{|}/', $in, -1, PREG_SPLIT_NO_EMPTY);

答案 1 :(得分:2)

按照stema的回答我会建议

  1. 使用正则表达式验证字符串
  2. 由于您无法为此目的使用捕获组,因此我会删除此正则表达式#{上的前导}和尾随split以及}{字符串
  3. 这应该会给你一个包含所有匹配项的数组。