RegExp匹配由一组有限字符组成的字符串,而不重用任何字符
我有很多像这样的人物: ABBCD
我有几个像这样的空格: _ _ _
有没有办法使用正则表达式匹配任何可以通过“拖动”可用字符到空白空间形成的字符串?
所以在这个例子中,这些是一些有效的匹配:
ABC ABB BCB DAB
但这些都是无效的:
AAB // Only one 'A' is available in the set BBB // Only two 'B's are available in the set
对不起,如果之前已经被询问过。
vks的解决方案可以正常工作 ,并且这里通过添加来优化以实现“_ _ _”规则:
^(?!(?:[^A]*A){2})(?!(?:[^B]*B){3})(?!(?:[^C]*C){2})(?!(?:[^D]*D){2})(?:[ABCD](?:\s|$)){3}
这是一个正则表达式演示 。
原始正则表达式的变化:
- 由于我们使用Java,因此删除捕获组 – Java正则表达式实现在匹配期间花费时间编写捕获的组。
- 锚
^
在前面移动以便于正则表达式的可读性。
正则表达式解释:
-
^
在比赛开始时断言位置。 -
(?!
Negative lookahead – 断言我们的位置与以下内容不匹配,而不移动指针: -
(?:[^A]*A){2}
两个“A” (字面字符),非“A”以最佳方式翻转。 -
)
关闭小组。 -
(?!(?:[^B]*B){3})
与上述组相同 – 断言匹配中没有三个“B” 。 -
(?!(?:[^C]*C){2})
断言匹配中没有两个“C” 。 -
(?!(?:[^D]*D){2})
断言匹配中没有两个“D” 。 -
(?:
非捕获组:匹配以下内容而不捕获。 -
[ABCD]
列表“A” , “B” , “C”或“D”中的任何字符。 -
(?:\s|$)
一个空格,或字符串的结尾。 -
){3}
三次 – 必须完全匹配序列三次才能满足“_ _ _”规则。
要使用正则表达式:
boolean fulfillsRule(String str) { Pattern tripleRule = Pattern.compile("^(?!(?:[^A]*A){2})(?!(?:[^B]*B){3})(?!(?:[^C]*C){2})(?!(?:[^D]*D){2})(?:[ABCD](?:\s|$)){3}"); return tripleRule.matcher(str).find(); }
(?!(.*?A){2,})(?!(.*?B){3,})(?!((.*?C){2,}))(?!((.*?D){2,}))^[ABCD]*$
你可以使用这样的东西。参见演示。
有趣的问题,这是我的想法:
(?m)^(?!.*([ACD]).*\1)(?!(?>.*?B){3})(?>[AD] ){2}[AD]$
使用(?m)
MULTILINE 修饰符 ,其中^
匹配行开始和$
line结束。
在regexplanet上测试 (点击Java); regex101 (非Java)
如果我理解正确,可用的字符组是A,B,B,C,D
。 如果字符串在您的示例中包含每个[ACD]
0或1或B
0-2 ,则该字符串应该有效。 我的模式由3部分组成:
-
(?!.*([ACD]).*\1)
用于行开始^
负前瞻以确保[ACD]
最多发生一次,通过捕获[ACD]
到\1
并检查,它确实在任何地方都不会发生 -
(?!(?>.*?B){3})
使用负前瞻,确保B
最多出现2次 。 -
finally
(?>[AD] ){2}[AD]$
确定总可用字符集,确保格式化,每个字母必须由空格预先确定或开始并检查长度。
这可以很容易地修改为其他需求。 另请参阅SO Regex常见问题解答