正则表达式:PHP的后视固定长度断言限制的解决方法

时间:2012-11-19 22:46:03

标签: php regex assert

我试图更多地了解环顾四周的断言,我发现this thread,他们的解决方案应该在某些引擎中工作,但不是PHP,因为PHP'要求后视断言是固定长度的。

我想要的是让相同的场景在PHP中运行,或者至少知道它是否可行。

我试图减少正则表达式规则的解释,所以它与我上面提到的线程不一样,但它遵循相同的原则。

需要匹配一个由三部分组成的字符串:

  • 以任意数量的字母数字字符开头
  • 不包含" abc - "接着是3到5个数字和/或连字符
  • 结束" .htm"或" .html"

所以,这些将匹配:

  • xxxyz-123.html
  • xx123-abc.htm
  • xxabc123.html
  • xxabc-123-45.htm

但这些不匹配:

  • xxabc-4324.htm
  • xxabc-1-2.html
  • XXAC-12-34.txt
  • xxabc-12345.htm

我一直尝试使用下面的正则表达式模式的某些变体,但它不起作用 - 这种特殊情况是因为固定长度限制:

.*(?<!abc-[\d-]{3,5})\.htm[^l]?$

我也使用了不同的测试字符串并且忘记了3-5个范围部分,只关注3个数字和/或连字符,并使用下面的正则表达式,它仍然无法工作,这就是我决定寻求帮助的原因:

.*(?<!abc-[\d-]{3})\.htm[^l]?$

你们这些正规英国大佬们能帮助我吗?

修改

这是我测试的PHP代码:

$regex = "/^(?!.*abc-[\d-]{3,5})[a-zA-Z0-9-]+\.html?$/";

foreach ( $matching2 as $k => $v ) {
    $matches = preg_match( $regex, $v );

    echo '"', $v, '"', ( $matches != 0 ) ? ' matches' : ' doesn\'t match', '<br />';
}

2 个答案:

答案 0 :(得分:2)

为什么你需要反过来看?为什么不直接使用?

^(?!.*abc-[\d-]{3,5}[^\d-])[a-zA-Z0-9-]+\.html?$

这将简单地开始查看字符串的开头,并且前瞻尝试在字符串中的任何位置(.*)查找不允许的字符串。如果是这样,前瞻使模式失败。这还包括要求,该字符串仅由字母数字和连字符组成。

这与您链接的问题所使用的解决方案相同。 Perl无法应对可变长度的lookbehinds。 只有 .NET可以。

另一个注意事项:如果你遇到一个例子,你实际上需要一个可变长度的lookbehind(但不是一个可变长度的前瞻)...反转字符串(和模式,也是, 当然)。 ;)

答案 1 :(得分:1)

您可能正在寻找正则表达式

^(?!.*abc-[\d-]{3,5}[^\d-])[A-Za-z0-9].*[.]html?$