在字符串中查找两个相同的字符(正则表达式)

3
我是一名初学正则表达式的人,需要帮助。我想要验证有两个相同字符跟着字母A,或者它们被分隔开(但仍然相等),并且在中间是字母A。我用例子来解释一下:
BBA -> true
ABB -> true
BAB -> true
CCA -> true
ABC -> false
BAC -> false
BBBA -> false (there have to be only two)
ABBB -> false (there have to be only two)

目前我有类似于这样的东西,但它不能正常工作:

(([B-Z])\1{2}A) | ([B-Z]{1}A[B-Z]{1}) | (A([B-Z])\1{2})

我知道我的答案离正确的还差得很远,如果有人能帮我一下,我将非常感激。

一般来说,你可能需要研究反向引用以及如何与捕获组一起使用它们,以便根据当前已捕获的字符匹配字符: https://stackoverflow.com/questions/21428545/java-regex-how-to-back-reference-capturing-groups-in-a-certain-context-when-the问题在于,在你的情况下,像[A-Z]{2}这样的东西将匹配 ABAZ 和任何其他 2 个符号的正则表达式,我没有看到一个好的方法来表达“从这个集合中重复相同的字母”,除了像 A{2}A | B{2}A | C{2}A 这样,或者使用带有反向引用的捕获组。 - Anton
1
但我会避免使用正则表达式来解决这种问题,因为它变得太复杂和脆弱。在正则表达式中提取前两个字母,然后在Java中检查它们是否相同。 - Anton
这个答案可能会对你有所帮助:https://dev59.com/K2Qn5IYBdhLWcg3wmIAs#16717823 - Dhiral Kaniya
3个回答

1
这可以相当优雅地完成:
\b(?=[A-Z]{3}\b)A?([B-Z])A?\1A?\b regex101演示
前瞻中的[A-Z]{3}断言序列的长度恰好为3个字母,由于两侧都有\b。 A?([B-Z])A?\ 1A?断言存在两个除A之外的相同字母实例,它可以在任何点上与A混合,而且由于两侧也被\b包围,断言没有混入其他内容。
这也可以推广到任意数量的重复: \b(?=[A-Z]{3}\b)(?:\1|(?!\2)([B-Z])()|(?!\3)A())+\b\2 只需要将{3}改为你想要的总字符数(即重复次数加上“A”的数量)。

在regex101上演示
在线尝试!(Java)


1
使用\b只匹配单词,对于每个|使用反向引用。
\b([B-Z])\1A|([B-Z])A\2|A([B-Z])\3\b

检查:

https://regexr.com/42bp0


1
非常感谢!它完美地发挥作用!我已经思考了几个小时如何解决它。现在我需要理解它的工作原理并继续学习。再次,非常感谢! - Gabriel
你正则表达式中的一个错误是([B-Z])\1{2}实际上是指3个相同的字符,因为([B-Z])已经指向了一个,而\1{2}指向了另外两个。 - Rocky Li
由于前两个选择中缺少尾随的\b,以及最后两个选择中缺少前导的\b,因此这会错误地匹配BABABBAA,以及ABABAABB。修复后的版本应为\b([A-Z])\1A\b|\b([A-Z])A\2\b|\bA([A-Z])\3\b或通过分组选择\b(?:([A-Z])\1A|([A-Z])A\2|A([A-Z])\3)\b - Deadcode

0
Pattern pattern = Pattern.compile("([B-Z])\\1A|A([B-Z])\\2|([B-Z])A\\3")

回溯引用穿过整个模式并跨越OR运算符。一般来说,它不适合于正则表达式解决方案,尽管其他人已经提到过。

请注意,您必须根据需要添加^和$以仅匹配此模式,如下所示:

"^([B-Z])\\1A\$|^A([B-Z])\\2\$|^([B-Z])A\\3\$"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接