PCRE匹配后(lookbehind)与由斜线和行尾分隔的捕获组

时间:2017-11-29 02:11:09

标签: php regex pcre

我的目标是在以下字符串中的propertyComplexity之后捕获{type}和{code}的正则表达式: -

/json/score/propertyComplexity/{type}/{code}

{type}和{code}是变量,可以是任何东西,例如。

/json/score/propertyComplexity

我已经开始使用以下表达式: -

(?<=propertyComplexity)\/(.*)\/|$

但这只捕获了2个斜杠之间的{type};捕获组的结束分隔符需要是斜线或行尾。

正则表达式需要在propertyComplexity之后的斜杠之后捕获所有单词,直到行尾结束。例如:

/json/score/propertyComplexity/{type}/{code}/{param3}/{param4}

应该产生4个匹配/捕获组; {type},{code},{param3},{param4}

如果它有帮助,这在处理WADL中的@path属性的上下文中。捕获的内容实际上是无关紧要的,因为它是将使用的匹配计数(与确定调用哪个WADL资源时传递的参数的计数进行比较)。

不要求网址有效性。

当WADL中的参数始终封装在{param}占位符中时,无需在斜杠上或之后进行匹配。

所以我只是在preg_match_all()== count($ this-&gt; passedArgs)中使用以下表达式

/{(.*?)}/

谢谢大家的贡献。答案正在颁发给Jaytea。

2 个答案:

答案 0 :(得分:1)

您可以结合以下表达式使用preg_match_all来实现您的目标:

/(?(?=^).*?propertyComplexity(?=(?:\/[^\/]+)*\/?$)|\G)\/\K([^\/]+)/

&#39; \ G&#39;断言在主题的第一个位置匹配,在这种情况下有效地表示它在最后一个匹配结束的位置匹配。这里的基本策略是在开始时验证字符串的格式,然后在后续轮次中一次捕获一个属性。

我不确定您对验证的要求有多严格,所以我保持简单。

答案 1 :(得分:0)

这是一个将正则表达式与explode()结合起来的解决方案,因为我很确定用PCRE分别捕获(或计算)重复组是不可能的。

正则表达式模式期望/之后的任何/propertyComplexity - 分隔段(我已经将斜线更加严格地预先设置)非空,因此允许任何非空内容,不仅仅是像{type}这样的大括号括起来的内容。

模式比它可能需要的要复杂一点,但它会使结果更加简洁(不需要修剪斜线)。

实际参数值将在数组$arguments中,但我遗漏了在结果中显示这些值的更加简短。

$urls = array(
  '/json/score/propertyComplexity',
  '/json/score/propertyComplexity/',
  '/json/score/propertyComplexity//', // invalid
  '/json/score/propertyComplexity/{type}',
  '/json/score/propertyComplexity/{type}/',
  '/json/score/propertyComplexity/{type}//', // invalid
  '/json/score/propertyComplexity/{type}/{code}',
  '/json/score/propertyComplexity/{type}/{code}/{param3}',
  '/json/score/propertyComplexity/{type}/{code}/{param3}/{param4}',
  '/json/score/propertyComplexity/{type}/{code}/{param3}/{param4}/{param5}'
);

foreach( $urls as $url ) {
  printf( 'testing %s' . PHP_EOL, $url );
  if( preg_match( '~(?<=/propertyComplexity)(?:/(?<arguments>[^/]+(/[^/]+)*))?(?:/?$)~', $url, $matches ) ) {
    $arguments = isset( $matches[ 'arguments' ] ) ? explode( '/', $matches[ 'arguments' ] ) : array();
    printf( '  URL is valid: argument count is %d' . PHP_EOL, count( $arguments ) );
  }
  else {
    echo '  URL is invalid' . PHP_EOL;
  }
  echo PHP_EOL;
}

View this example on eval.in

结果:

testing /json/score/propertyComplexity
  URL is valid: argument count is 0

testing /json/score/propertyComplexity/
  URL is valid: argument count is 0

testing /json/score/propertyComplexity//
  URL is invalid

testing /json/score/propertyComplexity/{type}
  URL is valid: argument count is 1

testing /json/score/propertyComplexity/{type}/
  URL is valid: argument count is 1

testing /json/score/propertyComplexity/{type}//
  URL is invalid

testing /json/score/propertyComplexity/{type}/{code}
  URL is valid: argument count is 2

testing /json/score/propertyComplexity/{type}/{code}/{param3}
  URL is valid: argument count is 3

testing /json/score/propertyComplexity/{type}/{code}/{param3}/{param4}
  URL is valid: argument count is 4

testing /json/score/propertyComplexity/{type}/{code}/{param3}/{param4}/{param5}
  URL is valid: argument count is 5