正则表达式检查集合的第一个和最后一个字符是不是不同
Posted
技术标签:
【中文标题】正则表达式检查集合的第一个和最后一个字符是不是不同【英文标题】:Regex expression to check if first and last char of set are different正则表达式检查集合的第一个和最后一个字符是否不同 【发布时间】:2021-07-19 20:25:02 【问题描述】:假设我有一串只有 a
和 b
的字符串,如下所示:
aaabbbbababab
如何构造一个正则表达式,只有当第二个和最后一个字符不同时才匹配给定的字符串?
这是我目前的尝试,完全相反(例如,如果第二个和最后一个字符相同,则匹配):
^[ab]([ab])[ab]*\1$
我正在使用正则表达式的 ECMAScript 实现。
【问题讨论】:
ab
重要吗?正则表达式是否还需要验证这些是字符串中仅有的 2 个字符?
是的,如果第二个字符是a
,那么最后一个字符必须是b
,而不是其他字符。
哦,好吧,所以***.com/a/67267084/2191572 是正确的,但如果ab
不重要,我确实提供了一个通用的解决方案。
您是否也需要允许单个字符,例如“a”?也许你可以试试:^(?!.(.).*\1$)[ab]+$
不,我希望字符串的长度 > 2
【参考方案1】:
只是为了替代,你可以尝试:
^[ab]3,(?<!^.\1.*(.))$
在线查看demo。
^
- 起始线锚点。
[ab]3,
- 3 次以上的字面意思是“a”或“b”。
(?<!^.\1.*(.)
- 否定后视断言最后一个字符与第二个字符不同。
$
- 结束线锚。
或者,您可以尝试负前瞻(奇怪的是,这在测试时效率最高):
^(?!.(.).*\1$)[ab]3,$
在线查看demo。
^
- 起始线锚点。
(?!.(.).*\1$)
- 断言第二个字符的负前瞻与结束行锚点之前的最后一个字符不同。
[ab]3,
- 3 次以上的字面意思是“a”或“b”。
$
- 结束线锚。
【讨论】:
【参考方案2】:您可以为第二个字符使用一个捕获组,如果它与捕获组 1 不同,则仅匹配最后一个字符。
^[ab]([ab])[ab]*(?!\1)[ab]$
^
字符串开始
[ab]
匹配 a 或 b(请注意,您可以省略 |
,因为它表示字符类中的管道字符
([ab])
捕获组 1,匹配 a 或 b
[ab]*
可选择匹配 a 或 b
(?!\1)
负前瞻,使用反向引用 \1
断言与第 1 组中捕获的值不同的值
[ab]$
匹配字符串末尾的 a 或 b
Regex demo
另一种选择是在捕获组之后立即进行断言
^[ab]([ab])(?![ab]*\1$)[ab]*$
Regex demo
或者,如果支持,负面的后视也可能起作用。 This page 显示了对 javascript 和lookbehinds 的兼容性
^[ab]([ab])[ab]*[ab]$(?<!\1)
Regex demo
【讨论】:
您为什么要切换到[a-b]
来获取其中一个 char 类?
@MonkeyZeus 这是一个错字,让我更新一下:-)【参考方案3】:
如果您不必验证整个字符串是一堆ab
s,那么我会选择通用的,例如:
^.(.).*(?!\1).$
^.
- 以一个字符开头
(.)
- 将第二个字符放入捕获组中
.*
- 可以选择捕获前进的所有内容
(?!\1).$
- 确保最终字符与第二个字符不同
https://regex101.com/r/k47PUu/1/
【讨论】:
以上是关于正则表达式检查集合的第一个和最后一个字符是不是不同的主要内容,如果未能解决你的问题,请参考以下文章
Python:检查列表中至少一个正则表达式是不是与字符串匹配的优雅方法
在Java中,如何在没有正则表达式的情况下查找字符串中的第一个字符是不是为大写