【问题标题】:PCRE match after (lookbehind) with capture groups delimited by slashes and end of linePCRE 匹配后(lookbehind),捕获组由斜线和行尾分隔
【发布时间】:2017-11-29 02:11:08
【问题描述】:

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

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

{type} 和 {code} 是变量,可以是任何东西,也可以什么都不是,例如

/json/score/propertyComplexity

我从以下表达式开始:-

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

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

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

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

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

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

网址有效性不是要求。

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

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

/{(.*?)}/

感谢所有贡献的人。答案正在颁发给 Jaytea。

【问题讨论】:

标签: php regex pcre


【解决方案1】:

你可以使用preg_match_all结合下面的表达式来实现你想要的:

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

'\G' 断言在主题的第一个位置匹配,在这种情况下,这实际上意味着它在最后一个匹配结束的位置匹配。这里的基本策略是在开始时验证字符串的格式,然后在后续轮次中一次捕获一个属性。

我不确定你想对你的验证有多严格,所以我保持得很简单。

【讨论】:

    【解决方案2】:

    这是一种将正则表达式与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
    

    【讨论】:

      猜你喜欢
      • 2021-11-26
      • 2013-07-22
      • 1970-01-01
      • 2013-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多