不确定说出这个的最好方法,所以我只举一个例子。假设我有角色a,b,c,d
。我想接受任何顺序中每个字符为0或1的字符串。 "ab"
"abcd"
"dcab"
等字符串都可以接受。是否可以使用正则表达式执行此操作?
我唯一想到的是((a|b|c|d){0,1}){0,4}
。然而,这不会起作用,因为它会接受诸如“aaaa”之类的字符串。
答案 0 :(得分:4)
问题似乎很容易。但事实并非如此。你去吧,
^([abcd])(?:(?!\1)([abcd]))?(?:(?!\1|\2)([abcd]))?(?:(?!\1|\2|\3)([abcd]))?$
减少一个,
^([abcd])((?!\1)[abcd])?((?!\1|\2)[abcd])?((?!\1|\2|\3)[abcd])?$
模式说明:
^
断言我们刚开始。([abcd])
第一个字符必须是字符类中的任何字符( a或b或c或d )。第一个角色是通过捕获组捕获的。(?!\1)[abcd]
第二个字符必须是字符类中的任何字符,但它不能与第一个字符相似。此角色被捕获((?!\1)[abcd])?
,我们将整体视为可选。如果第二个字符存在则必须满足上述条件。((?!\1|\2)[abcd])?
来自char类的任何字符,但不包含第一个或第二个字符。捕获此角色,我们将此角色作为可选角色。((?!\1|\2|\3)[abcd])?
来自char类的任何字符,但不是第一个,第二个或第三个字符。捕获此角色,我们将此角色作为可选角色。$
断言我们到底。 li>
或强>
^(?:(?!(.).*\1)[abcd])+$
模式说明:
(?!(.).*\1)
否定前瞻声称人物不会被重复。(?:(?!(.).*\1)[abcd])+
现在,只有在没有重复的字符时,才匹配字符类中的一个或多个字符( a或b或c或d )。因此它最多只能匹配四个字符( 1到4 )。或强>
通过PCRE动词(*SKIP)(*F)
,
^.*(.).*\1.*$(*SKIP)(*F)|^[abcd]+$
模式说明:
^.*(.).*\1.*$
匹配所有重复字符的行。(*SKIP)(*F)
使上一场比赛失败。也就是说,正则表达式匹配标记将位于除了具有重复字符的行之外的所有行上。现在它尝试将|
运算符右侧的模式与不具有任何重复字符的行匹配。^
断言我们刚开始。 [abcd]+
字符类中的任何字符一次或多次。因为我们已经跳过了所有重复字符的行,所以它不匹配aba
或bba
等。
$
断言我们到底。 p>
答案 1 :(得分:2)
嗯,我觉得这很有意思。怎么样:
^(?>([abcd])(?!.*\1))+$
在第一个capture group中捕获[abcd]
并使用否定lookahead进行检查,如果它本身没有被跟踪。 +
整件事中的一件或多件。如果原子组不受特定正则表达式风格的支持,可能希望将(?>
更改为(?:
非捕获组。
答案 2 :(得分:2)