【问题标题】:PCRE: DEFINE statement for lookaroundsPCRE:用于环视的 DEFINE 语句
【发布时间】:2016-07-07 15:36:19
【问题描述】:

深入正则表达式的世界,我在PCRE 中发现了DEFINE 语句。
我有以下代码(它定义了一个小写字母、一个大写字母和anA 组(我知道此时它相当没用,谢谢:):

(?(DEFINE)
 (?<lowercase>(?=[^a-z]*[a-z])) # lowercase
 (?<uppercase>(?=[^A-Z]*[A-Z])) # uppercase
 (?<anA>A(?=B))
)
^(?&anA)

现在,我想知道如何将前瞻(本例中为lowercase)与anA 部分结合起来?诚然,很难找到有关DEFINE 语法的适当文档。这是a regex101.com fiddle
为了让它更清楚一些,我想有机会将子程序结合起来。例如,对于上面的示例(即验证需要有A 后跟B 和一些小写字母的密码),我可以do the following

^(?=[^a-z]*[a-z]).*?A(?=B).*

上面的子程序如何做到这一点?

编辑:作为参考,我最终使用了following construct

(?(DEFINE)
 (?<lc>(?=[^a-z\n]*[a-z]))      # lowercase
 (?<uc>(?=[^A-Z\n]*[A-Z]))      # uppercase
 (?<digit>(?=[^\d\n]*\d))       # digit
 (?<special>(?=.*[!@]+))        # special character
)
^(?&lc)(?&uc)(?&digit)(?&special).{6,}$

【问题讨论】:

  • Jan,您能否澄清一下如何将前瞻(本例中为lowercase)与anA 部分结合 部分?你想在你的输入字符串中匹配什么?
  • 您没有在演示中将 x-flag 用于注释模式(在 ^ 行首之前匹配换行符)。也许这会混淆你的期望。 Rexegg 有一些关于predefined subroutes 的章节。或pcre docs.
  • @WiktorStribiżew:a) 用于学习目的,b) 用于密码验证。我知道我可以自己编写前瞻,但是我希望它是块式的。我会更新问题以使其更清楚。
  • 只需递归子模式,就像你已经使用 anA: regex101.com/r/yL1cS5/1
  • 只有一个警告:所有子例程调用,无论是否递归,总是被视为原子组。也就是说,一旦子例程匹配了一些主题字符串,它就永远不会重新输入,即使它包含未尝试的替代项并且随后出现匹配失败。在子例程调用期间设置的任何捕获括号都将在之后恢复为之前的值。

标签: php regex pcre


【解决方案1】:

如何将前瞻(本例中为lowercase)与anA 部分结合起来

您可以使用 (?&amp;lowercase) 命名的子例程调用,以与使用 anA 相同的方式递归子模式:

/(?(DEFINE)
   (?<lowercase>(?=[^a-z]*[a-z])) # lowercase
   (?<uppercase>(?=[^A-Z]*[A-Z])) # uppercase
   (?<anA>A(?=B))
  )
  ^(?&lowercase)(.*?)((?&anA)).*
/mgx

请参阅regex demo。请注意,您需要在 regex101.com 上使用 /x 修饰符指定 VERBOSE/IgnorePatternWhitespace/Freespace 模式才能使此模式起作用。

如果您还想定义.*.*? 子模式,请注意一个警告(请参阅PCRE Man Pages):

所有子例程调用,无论是否递归,都被视为原子组。也就是说,一旦子例程匹配了一些主题字符串,它就永远不会重新输入,即使它包含未尝试的替代项并且随后出现匹配失败。在子例程调用期间设置的任何捕获括号都将在之后恢复为之前的值。

【讨论】:

  • 再次感谢 Wiktor(链接已损坏)。
猜你喜欢
  • 1970-01-01
  • 2012-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多