2

我正在尝试匹配这样的字符串:

{{name|arg1|arg2|...|argX}}

用正则表达式

我正在preg_match使用

/{{(\w+)\|(\w+)(?:\|(.+))*}}/

但是每当我使用两个以上的参数时,我都会得到类似的东西

Array
(
    [0] => {{name|arg1|arg2|arg3|arg4}}
    [1] => name
    [2] => arg1
    [3] => arg2|arg3|arg4
)

前两项不能包含空格,其余的可以。也许我在这方面工作太久了,但我找不到错误 - 任何帮助将不胜感激。

谢谢简

4

5 回答 5

4

不要对这些简单的任务使用正则表达式。你真正需要的是:

$inner = substr($string, 2, -2);
$parts = explode('|', $inner);

# And if you want to make sure the string has opening/closing braces:
$length = strlen($string);
assert($inner[0] === '{');
assert($inner[1] === '{');
assert($inner[$length - 1] === '}');
assert($inner[$length - 2] === '}');
于 2009-08-25T14:19:23.653 回答
3

The problem is here: \|(.+)

Regular expressions, by default, match as many characters as possible. Since . is any character, other instances of | are happily matched too, which is not what you would like.

To prevent this, you should exclude | from the expression, saying "match anything except |", resulting in \|([^\|]+).

于 2009-08-25T14:46:21.643 回答
0

Of course you would get something like this :) There is no way in regular expression to return dynamic count of matches - in your case the arguments.

Looking at what you want to do, you should keep up with the current regular expression and just explode the extra args by '|' and add them to an args array.

于 2009-08-25T14:49:44.587 回答
0

事实上,这是来自 PCRE 手册:

当重复捕获子模式时,捕获的值是与最终迭代匹配的子字符串。例如,在 (tweedle[dume]{3}\s*)+ 匹配“tweedledum tweedledee”之后,捕获的子字符串的值为“tweedledee”。但是,如果存在嵌套的捕获子模式,则相应的捕获值可能已在之前的迭代中设置。例如,在 /(a|(b))+/ 匹配“aba”之后,第二个捕获的子字符串的值为“b”。

于 2009-08-25T14:56:51.300 回答
0

应该适用于从 1 到N个参数的任何地方

<?php

$pattern = "/^\{\{([a-z]+)(?:\}\}$|(?:\|([a-z]+))(?:\|([a-z ]+))*\}\}$)/i";

$tests = array(
    "{{name}}"                          // should pass
  , "{{name|argOne}}"                   // should pass
  , "{{name|argOne|arg Two}}"           // should pass
  , "{{name|argOne|arg Two|arg Three}}" // should pass
  , "{{na me}}"                         // should fail
  , "{{name|arg One}}"                  // should fail
  , "{{name|arg One|arg Two}}"          // should fail
  , "{{name|argOne|arg Two|arg3}}"      // should fail
  );

foreach ( $tests as $test )
{
  if ( preg_match( $pattern, $test, $matches ) )
  {
    echo $test, ': Matched!<pre>', print_r( $matches, 1 ), '</pre>';
  } else {
    echo $test, ': Did not match =(<br>';
  }
}
于 2009-08-25T14:39:51.983 回答