这是Regular expression which matches at least two words from a list的后续行动:
如何编写一个与列表中至少两个不同字匹配的正则表达式?
例如,根据列表"foo"
,"bar"
,"baz"
,我希望正则表达式匹配"foo..bar"
但不匹配"foo..foo"
和{{1} }。
就像在原始问题中一样,我想避免在正则表达式中重复单词列表(如果我的黑名单长度为30而不是3,如示例中那样?)
答案 0 :(得分:2)
如果您使用的正则表达式引擎支持它,您可以使用负前瞻和反向引用来执行此操作:
(foo|bar|baz).*(?!\1)(foo|bar|baz)
(?!\1)
表示"未跟随第一个捕获组中的那个"。
为了不重复两次列表,pcre正则表达式引擎提供了不同的语法:
(foo|bar|baz).*(?!\1)(?1)
(foo|bar|baz).*(?!\g{1})\g<1>
(?<list>foo|bar|baz).*(?!\g{list})\g<list>
(?(DEFINE)(?<list>foo|bar|baz))(\g<list>).*(?!\1)\g<list>
使用Ruby:
(foo|bar|baz).*(?!\k<1>)\g<1>
(?<list>foo|bar|baz).*(?!\k<list>)\g<list>
(?<list>foo|bar|baz){0}\g<list>.*(?!\k<list>)\g<list>
但是如果正则表达式引擎没有重用子模式的功能,你可以尝试这种模式(适用于pcre,Python re模块,Java,.NET,Ruby但不能使用Javascript或XRegExp) ):
(?:(?!\1)(foo|bar|baz).*){2}
说明:
在开始时(第一次),没有定义捕获组,也没有定义反向引用\1
。正则表达式引擎忽略了先行条件(请注意,这意味着正则表达式引擎不会将(?!\1)
视为(?!)
,而是选择跳过测试!)。然后捕获列表中的第一个单词,第二次现在定义了反向引用\1
,并且前瞻功能完成了它的工作。
对于R语言,您可以使用参数perl=TRUE
使其工作并转义反斜杠(如在Java中):
(?:(?!\\1)(foo|bar|baz).*){2}