不确定最好的表达方式,所以我只举一个例子。假设我有字符 a,b,c,d
.我想接受以任何顺序包含 0 或 1 个字符的任何字符串。字符串如 "ab"
"abcd"
"dcab"
都是可以接受的。是否可以仅使用正则表达式来做到这一点?
我唯一想到的是((a|b|c|d){0,1}){0,4}
.但是,这不起作用,因为它会接受诸如“aaaa”之类的字符串。
最佳答案
问题似乎很简单。但事实并非如此。干得好,
^([abcd])(?:(?!\1)([abcd]))?(?:(?!\1|\2)([abcd]))?(?:(?!\1|\2|\3)([abcd]))?$
DEMO
减少了一个,
^([abcd])((?!\1)[abcd])?((?!\1|\2)[abcd])?((?!\1|\2|\3)[abcd])?$
DEMO
图案说明:
^
断言我们处于开始阶段。 ([abcd])
第一个字符必须是字符类(a 或 b 或 c 或 d)中的任何一个。而第一个字符是通过捕获组捕获的。 (?!\1)[abcd]
第二个字符必须是字符类中的任何字符,但不能与第一个字符相似。而这个角色被抓获 ((?!\1)[abcd])?
我们将整体设为可选。如果存在第二个字符,则它必须满足上述条件。 ((?!\1|\2)[abcd])?
char 类中的任何字符,但不是第一个或第二个字符。该角色已被捕获,我们将其设为可选。 ((?!\1|\2|\3)[abcd])?
char 类中的任何字符,但不是第一个、第二个或第三个字符。该角色已被捕获,我们将其设为可选。 $
断言我们到了最后。 或
^(?:(?!(.).*\1)[abcd])+$
图案说明:
(?!(.).*\1)
负前瞻断言字符不会重复。 (?:(?!(.).*\1)[abcd])+
现在,仅当没有重复字符时,它才会匹配字符类(a 或 b 或 c 或 d)中的一个或多个字符。所以它最多只能匹配四个字符(1 到 4)。 DEMO
或
通过PCRE动词
(*SKIP)(*F)
,^.*(.).*\1.*$(*SKIP)(*F)|^[abcd]+$
图案说明:
^.*(.).*\1.*$
匹配所有具有重复字符的行。 (*SKIP)(*F)
使之前的匹配失败。也就是说,正则表达式匹配标记将在所有行上,除了具有重复字符的行。现在它尝试匹配 |
右侧的模式运算符在没有任何重复字符的行上。 ^
断言我们处于开始阶段。 [abcd]+
来自字符类的任何字符一次或多次。因为我们已经跳过了所有有重复字符的行,所以它不会匹配 aba
或 bba
等$
断言我们到了最后。 DEMO
关于regex - 确定行是否包含 1-4 个特定字符的正则表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25954779/