regex查找一对相邻的数字,它们周围有不同的数字

t9aqgxwy  于 12个月前  发布在  其他
关注(0)|答案(4)|浏览(106)

我想知道是否有两个相同的数字彼此相邻,并且这对数字后面和前面的数字是不同的。
比如说,
123456678应该匹配,因为有一个双6,
1234566678不应该匹配,因为没有不同周围数字的双精度数。12334566应该匹配,因为有两个3。
到目前为止,我只对1有效,只要double不在字符串的开头或结尾,但是我可以通过在开头和结尾添加一个字母来处理。

^.*([^1]11[^1]).*$

字符串
我知道我可以用[0-9]代替1,但问题是它们都是相同的数字。

xn1cxnb4

xn1cxnb41#

我把答案分为四个部分。
第一部分包含了我对这个问题的解决方案。对其他内容不感兴趣的读者可以跳过其他部分。
剩下的三个部分是关于识别前有一个不同的数字后有一个不同的数字的相等的数字对。三个部分中的第一个部分匹配它们;另外两个部分将它们捕获在一组中。
我把最后一部分包括进来,因为我想和那些不熟悉它的人分享 The Greatest Regex Trick Ever,因为我发现它非常酷,聪明,但很简单。这里记录了它。预先警告,为了制造悬念,该链接的作者在鼓声揭示之前包括了一个冗长的序言。

判断一个字符串是否包含两个连续相等的数字,前面是一个不同的数字,后面是一个不同的数字

可以按如下方式测试字符串:

import re

r = r'(\d)(?!\1)(\d)\2(?!\2)\d'
arr = ["123456678", "1123455a666788"]
for s in arr:
  print(s, bool(re.search(r, s)) )

字符串
显示

123456678 True
1123455a666788 False


运行Python代码|Start your engine! 1
正则表达式引擎执行以下操作。

(\d)    : match a digit and save to capture group 1 (preceding digit)
(?!\1)  : next character cannot equal content of capture group 1
(\d)    : match a digit in capture group 2 (first digit of pair)
\2      : match content of capture group 2 (second digit of pair)
(?!\2)  : next character cannot equal content of capture group 2
\d      : match a digit


(?!\1)(?!\2)是 * 负lookaheads*。

使用Python的 regex 模块匹配具有所需属性的连续数字对

您可以使用下面的正则表达式和Python的regex模块来获得匹配的数字对。

r'(\d)(?!\1)\K(\d)\2(?=\d)(?!\2)'


Regex Engine
正则表达式引擎执行以下操作。

(\d)    : match a digit and save to capture group 1 (preceding digit)
(?!\1)  : next character cannot equal content of capture group 1
\K      : forget everything matched so far and reset start of match
(\d)    : match a digit in capture group 2 (first digit of pair)
\2      : match content of capture group 2 (second digit of pair)
(?=\d)  : next character must be a digit
(?!\2)  : next character cannot equal content of capture group 2


(?=\d)是一个 * 积极的前瞻 *。(?=\d)(?!\2)可以替换为(?!\2|$|\D)

保存具有所需属性的连续数字对到捕获组

获取匹配数字对的另一种方法(不需要正则表达式模块)是从以下正则表达式的匹配项中提取捕获组2的内容。

r'(\d)(?!\1)((\d)\3)(?!\3)(?=\d)'


Re engine
执行以下操作。

(\d)    : match a digit in capture group 1
(?!\1)  : next character does not equal last character
(       : begin capture group 2
  (\d)  : match a digit in capture group 3
  \3    : match the content of capture group 3
)       : end capture group 2
(?!\3)  : next character does not equal last character
(?=\d)  : next character is a digit

使用 The Greatest Regex Trick Ever 来识别具有所需属性的连续数字对

我们使用下面的正则表达式来匹配字符串。

r'(\d)(?=\1)|\d(?=(\d)(?!\2))|\d(?=\d(\d)\3)|\d(?=(\d{2})\d)'


当有匹配时,我们不注意哪个字符被匹配,而是检查捕获组4((\d{2}))的内容,我将在下面解释。
The Trick in action
交替的前三个组成部分对应于四位数的字符串可能不具有第二位和第三位相等,第一位和第二位不相等以及第三位和第四位相等的属性的方式。它们是:

(\d)(?=\1)        : assert first and second digits are equal    
\d(?=(\d)(?!\2))  : assert second and third digits are not equal
\d(?=\d(\d)\3)    : assert third and fourth digits are equal


因此,如果有一个数字匹配,并且交替的前三个部分失败,则最后一个部分(\d(?=(\d{2})\d))必须成功,并且它包含的捕获组(#4)必须包含具有所需属性的两个相等的数字(需要最后一个\d来Assert感兴趣的数字对后面跟着一个数字)。
如果存在匹配,我们如何确定交替的最后一部分是否是匹配的部分?
当这个正则表达式匹配一个数字时,我们对这个数字不感兴趣。相反,我们会寻找第4组((\d{2}))。如果该组是空的,我们就得出结论,交替的前三个组成部分中有一个匹配了这个数字,这意味着匹配的数字后面的两个数字不具有等于和不等于它们之前和之后的数字的属性。
然而,如果捕获组4不为空,则意味着交替的前三个部分中没有一个匹配该数字,因此交替的最后一部分必须匹配,并且捕获组4中保存的匹配数字之后的两个数字具有所需的属性。
1.移动光标查看详细说明。

kq4fsx7k

kq4fsx7k2#

使用正则表达式,使用基于(*SKIP)(*FAIL)的模式的PyPi regex模块要方便得多:

import regex
rx = r'(\d)\1{2,}(*SKIP)(*F)|(\d)\2'
l = ["123456678", "1234566678"]
for s in l:
  print(s, bool(regex.search(rx, s)) )

字符串
查看Python演示。输出:

123456678 True
1234566678 False

Regex详细信息

  • (\d)\1{2,}(*SKIP)(*F)-一个数字,然后出现两次或多次相同的数字
  • |-或
  • (\d)\2-一个数字,然后是相同的数字。

关键是匹配所有相同的3个或更多数字的块并跳过它们,然后匹配两个相同数字的块。
参见regex demo

7bsow1i6

7bsow1i63#

受Wiktor Stribienew的启发,使用re交替的另一种变体是检查捕获组的存在,该捕获组包含两个不被相同数字包围的相同数字的正匹配。
在这种情况下,检查第3组。

((\d)\2{2,})|\d(\d)\3(?!\3)\d

字符串
Regex demo|Python demo

  • (捕获组1
  • (\d)\2{2,}捕获组2,匹配1个数字并重复相同的数字2+次
  • )关闭组
  • |
  • \d(\d)匹配一个数字,捕获组3中的一个数字
  • \3(?!\3)\d匹配与第3组中相同的数字。匹配第4位数字,但不应与第3组数字相同

例如

import re

pattern = r"((\d)\2{2,})|\d(\d)\3(?!\3)\d"
strings = ["123456678", "12334566", "12345654554888", "1221", "1234566678", "1222", "2221", "66", "122", "221", "111"]

for s in strings:
    match = re.search(pattern, s)
    if match and match.group(3):
        print ("Match: " + match.string)
    else:
        print ("No match: " + s)


输出

Match: 123456678
Match: 12334566
Match: 12345654554888
Match: 1221
No match: 1234566678
No match: 1222
No match: 2221
No match: 66
No match: 122
No match: 221
No match: 111


例如,如果2或3位数字也可以匹配,则可以检查组2

(\d)\1{2,}|(\d)\2


Python demo

p8ekf7hl

p8ekf7hl4#

你也可以用一个简单的方法。

import re
l=["123456678",
"1234566678",
"12334566 "]
for i in l:
    matches = re.findall(r"((.)\2+)", i)
    if any(len(x[0])!=2 for x in matches):
        print "{}-->{}".format(i, False)
    else:
        print "{}-->{}".format(i, True)

字符串
您可以根据自己的规则进行自定义。
输出量:

123456678-->True
1234566678-->False
12334566 -->True

相关问题