1

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

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

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

/#{(\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"
}

似乎没有解析中间参数(这对我来说看起来很奇怪)。

4

2 回答 2

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);
于 2012-04-30T11:10:10.470 回答
2

按照stema的回答,我建议

  1. 使用您的正则表达式验证字符串
  2. 因为你不能为此目的使用捕获组,所以我会去掉前导#{和尾随},然后split是这个正则表达式上的字符串}{

这应该为您提供所有匹配项的数组。

于 2012-04-30T12:05:56.153 回答