与OR运算符匹配第一个规则后,Regex不会停止评估

See*_*ker 9 python regex

我在python中有正则表达式匹配问题我有一个字符串如下:

test_str = ("ICD : 12123575.007787. 098.3,\n"
    "193235.1, 132534.0, 17707.1,1777029, V40‚0, 5612356,9899\n")
Run Code Online (Sandbox Code Playgroud)

我的正则表达式有两个主要组绑定在一起|,正则表达式如下:

  regex =   r"((?<=ICD\s:\s).*\n.*)|((?<=ICD\s).*)"
Run Code Online (Sandbox Code Playgroud)

让我们打电话给他们(A | B).哪里A = ((?<=ICD\s:\s).*\n.*)B = ((?<=ICD\s).*).根据文档的 |工作方式,如果A匹配,它将不会进一步B.

现在我的问题是,当我使用上面提到的正则表达式test_str.它匹配B但不适合A.但是如果我A只用正则表达式搜索(即((?<=ICD\s:\s).*\n.*)),那么test_string它与正则表达式匹配A.所以我的问题是,为什么A|B正则表达式与组不匹配A并停止.以下是我的python代码:

import re

regex = r"((?<=ICD\s:\s).*\n.*)|((?<=ICD\s).*)"

test_str = ("ICD : 12123575.007787. 098.3,\n"
    "193235.1, 132534.0, 17707.1,1777029, V40‚0, 5612356,9899\n")

matches = re.search(regex, test_str)
if matches:
    print ("Match was found at {start}-{end}: {match}".format(
        start = matches.start(), 
        end = matches.end(), 
        match = matches.group()))

    for groupNum in range(0, len(matches.groups())):
        groupNum = groupNum + 1

        print ("Group {groupNum} found at {start}-{end}: {group}".format(
            groupNum = groupNum, 
            start = matches.start(groupNum), 
            end = matches.end(groupNum), 
            group = matches.group(groupNum)))
Run Code Online (Sandbox Code Playgroud)

输出:

Match was found at 4-29: : 12123575.007787. 098.3,
Group 1 found at -1--1: None
Group 2 found at 4-29: : 12123575.007787. 098.3,
Run Code Online (Sandbox Code Playgroud)

Python小提琴

对不起,如果您无法理解.我不知道为什么Group 1 found at -1--1: None不匹配.让我知道如果你了解它可能是什么原因.

Ara*_*Fey 10

发生这种情况的原因是因为正则表达式从左到右搜索匹配,而正则表达式的右半部分先前匹配.这是因为左表达式具有更长的lookbehind:(?<=ICD\s:\s)需要两个以上的字符(?<=ICD\s).

test_str = "ICD : 12123575.007787. 098.3,\n"
#                 ^ left half of the regex matches here
#               ^ right half of the regex matches here
Run Code Online (Sandbox Code Playgroud)

换句话说,你的正则表达基本上就像(?<=.{3})(?<=.).如果你尝试过re.search(r'(?<=.{3})|(?<=.)', some_text),很明显正则表达式的右侧首先匹配,因为它的后观更短.


您可以通过添加负前瞻来阻止正则表达式的右半部分过早匹配来解决此问题:

regex = r"((?<=ICD\s:\s).*\n.*)|((?<=ICD\s)(?!:\s).*)"
#                                          ^^^^^^^

test_str = "ICD : 12123575.007787. 098.3,\n"
#                 ^ left half of the regex matches here
#          right half of the regex matches doesn't match at all
Run Code Online (Sandbox Code Playgroud)