正则表达式,用于确定行是否包含1-4个特定字符

时间:2014-09-21 01:01:51

标签: regex

不确定说出这个的最好方法,所以我只举一个例子。假设我有角色a,b,c,d。我想接受任何顺序中每个字符为0或1的字符串。 "ab" "abcd" "dcab"等字符串都可以接受。是否可以使用正则表达式执行此操作?

我唯一想到的是((a|b|c|d){0,1}){0,4}。然而,这不会起作用,因为它会接受诸如“aaaa”之类的字符串。

3 个答案:

答案 0 :(得分:4)

问题似乎很容易。但事实并非如此。你去吧,

^([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]+字符类中的任何字符一次或多次。因为我们已经跳过了所有重复字符的行,所以它不匹配ababba等。

  • $断言我们到底。

DEMO

答案 1 :(得分:2)

嗯,我觉得这很有意思。怎么样:

^(?>([abcd])(?!.*\1))+$

在第一个capture group中捕获[abcd]并使用否定lookahead进行检查,如果它本身没有被跟踪。 +整件事中的一件或多件。如果原子组不受特定正则表达式风格的支持,可能希望将(?>更改为(?:非捕获组。

test at regex101; Regex FAQ

答案 2 :(得分:2)

Jonny 5 +1
这是我的模式

^(?!.*(.).*\1)([abcd]+)$  

Demo