python 正则表达式,其中一组选项最多可以以任何顺序在列表中出现一次

Har*_*nry 22 python regex perl

我想知道 python 或 perl 中是否有任何方法可以构建一个正则表达式,您可以在其中定义一组选项,这些选项最多可以以任何顺序出现一次。例如,我想要 的导数foo(?: [abc])*,其中a, b,c只能出现一次。所以:

foo a b c
foo b c a
foo a b
foo b
Run Code Online (Sandbox Code Playgroud)

都是有效的,但是

foo b b
Run Code Online (Sandbox Code Playgroud)

不会是

anu*_*ava 13

您可以将此正则表达式与捕获组和负前瞻一起使用:

对于,您可以将此变体与前向引用一起Perl使用:

^foo((?!.*\1) [abc])+$
Run Code Online (Sandbox Code Playgroud)

正则表达式演示

正则表达式详细信息:

  • ^: 开始
  • foo: 匹配foo
  • (:启动捕获组#1
    • (?!.*\1):负向前瞻断言我们与输入中任何位置的捕获组 #1 中的内容都不匹配
    • [abc]:匹配空格后跟aorbc
  • )+:结束捕获组#1。重复此组 1 次以上
  • $: 结尾

如前所述,此正则表达式使用称为“前向引用”的功能,该功能是对稍后出现在正则表达式模式中的组的反向引用。JGsoft、.NET、Java、Perl、PCRE、PHP、Delphi 和 Ruby 允许前向引用,但 Python 不允许。


以下是Python 的相同正则表达式的解决方法,不使用前向引用:

^foo(?!.* ([abc]).*\1)(?: [abc])+$
Run Code Online (Sandbox Code Playgroud)

在这里,我们在重复组之前使用负前瞻来检查是否存在允许的子字符串(即)的任何重复,并使匹配失败[abc]

正则表达式演示 2


The*_*ird 6

您可以断言右侧的空格和字母没有第二个匹配项:

foo(?!(?: [abc])*( [abc])(?: [abc])*\1)(?: [abc])*
Run Code Online (Sandbox Code Playgroud)
  • foo按字面意思匹配
  • (?!负前瞻
    • (?: [abc])*匹配空格和 ab 或 c 的可选重复
    • ( [abc])捕获组,用于与相同的反向引用进行比较
    • (?: [abc])*再次匹配空格和 ab 或 c
    • \1向后引用组 1
  • )关闭前瞻
  • (?: [abc])*匹配可选的重复项或空格以及 ab 或 c

正则表达式演示

如果不想只匹配 foo,可以将量词改为 1 或更多(?: [abc])+


Perl 中重用第一个子模式的变体,使用(?1)它引用捕获组([abc])

^foo ([abc])(?: (?!\1)((?1))(?: (?!\1|\2)(?1))?)?$
Run Code Online (Sandbox Code Playgroud)

正则表达式演示