Ruby正则表达式用于使用负先行的逗号分隔的唯一数字

nzrxty8p  于 11个月前  发布在  Ruby
关注(0)|答案(2)|浏览(75)

下面是一个正则表达式,它匹配一个以逗号分隔的数字列表,并且只允许输入唯一的数字:

^(?!.*\b(\d+)\b.*\b\1\b)(\d)(,(\d))*$

字符串
例如,它允许1,2,3,但不允许1,1或2,1,1。
有没有人能用简单的语言解释一下这是怎么回事?
我感到困惑的地方是否定的lookaheadAssert。
语法为:X(?!Y),它表示“搜索X,但仅当后面不跟Y时”。
参考:https://javascript.info/regexp-lookahead-lookbehind#negative-lookahead
但是在我展示的正则表达式中,它并不遵循上面的语法。那么它是如何工作的呢?
当它匹配1,2,3时,会发生什么匹配过程?
当它不匹配2,1,1时,会发生什么匹配过程?
当匹配1,2,3或2,1,1时,它们是首先与正则表达式(\d)(,(\d))*的后续部分匹配,然后将其匹配结果Assert为与负前瞻部分(?!.*\b(\d+)\b.*\b\1\b)匹配,还是首先运行负前瞻部分,然后运行剩余部分?
此外,如果我在负前瞻部分中删除\b前后的.*,则它也开始匹配1,1或2,1,1。那么,在负前瞻部分中删除的.*的意义是什么?
注意:我想在我的Ruby代码中使用正则表达式,以防它对通知很重要。
正则表达式的源引用为
https://stackoverflow.com/a/45946721/936494
https://stackoverflow.com/a/45944821/936494
谢谢.

kcwpcxri

kcwpcxri1#

消极前瞻

(?!.*\b(\d+)\b.*\b\1\b)

字符串
跟随一个绳的缠绕锚(^),Assert,“情况并非如此((?!...))在跳过零个或多个字符后,(线路终结器除外)(.*),则存在由一个或多个数字组成的字符串(\d+),保存到捕获组1((\d+)),前后都有一个单词边界(\b),后面是一个或多个字符(行终止符除外)(.*),后面是捕获组1的内容(\1),前面和后面是单词边界”。
因此,对于字符串'a 12, *34 *12',负向前查找失败(因为'12'前后都有一个字边界,所以是重复的),而对于字符串'a 12, *34 512',它会成功。(尽管重复了'12',第二个'12'前面没有字边界)如果lookahead失败,则不可能有匹配,因此不计算正则表达式的其余部分。如果lookahead成功,则正则表达式引擎继续计算正则表达式的其余部分。
由于正则表达式以字符串开头的锚(^)开始,如果满足,则前瞻不会将正则表达式的字符串指针从字符串的开头移动,在这种情况下,正则表达式实际上变为

^(\d)(,(\d))*$


例如,这满足'1,2,3''1'将保存到捕获组2(捕获组1用于前瞻),',2'将被保存到捕获组3,'2'将被保存到捕获组4,',3'将被保存到捕获组3(',2'),'3'将被保存到捕获组4('2')。Demo
考虑到正则表达式中跟在负前瞻后面的部分,我们可以看到负前瞻可以收紧如下1:

^(?!(?:\d,)*(\d),(?:\d,)*\1(?=,|\z))(\d)(,(\d))*$


Demo
1.为了测试正则表达式对多个字符串的影响,我在链接中使用了正向前向(?=,|$)(而不是(?=,|\z))。

nfeuvbwi

nfeuvbwi2#

你必须与排除一致(顶部)

^
(?!
   .* \b 
   ( \d+ )                       # (1)
   \b .* \b \1 \b 
)

字符串
与底部

( \d+ )                       # (2)
(                             # (3 start)
   ,
   ( \d+ )                       # (4)
)*                            # (3 end)
$


在整个过程中使用 \d+
如果你只需要一个数字\d,那么在整个过程中使用它。

^(?!.*\b(\d+)\b.*\b\1\b)(\d+)(,(\d+))*$


https://regex101.com/r/EnAPJW/1

相关问题