[Python] Negative lookahead regex in `re.subn()` context

Discussão em 'Python' iniciado por Stack, Fevereiro 17, 2025.

  1. Stack

    Stack Membro Participativo

    I am trying to use regular expressions to replace numeric ranges in text, such as "4-5", with the phrase "4 to 5".

    The text also contains dates such as "2024-12-26" that should not be replaced (should be left as is).

    The regular expression (\d+)(\-)(\d+) (attempt one below) is clearly wrong, because it falsely matches dates.

    Using a negative lookahead expression, I came up with the regex (?!\d+\-\d+\-)(\d+)(\-)(\d+) instead (attempt two below), which correctly matches "4-5" while rejecting "2024-12-26".

    However, attempt_two does not behave correctly in a re.subn() context, because although it rejects "2024-12-26", the search continues on to match (and replace) the substring "12-26":

    import re

    text = """
    2024-12-26
    4-5
    78-79
    """

    attempt_one = re.compile(r"(\d+)(\-)(\d+)")
    attempt_two = re.compile(r"(?!\d+\-\d+\-)(\d+)(\-)(\d+)")

    print("Attempt one:")
    print(re.match(attempt_one, "4-5")) # Match: OK
    print(re.match(attempt_one, "2024-12-26")) # Match: False positive
    new_text, _ = re.subn(attempt_one, r"\1 to \3", text) # Incorrect substitution
    print(new_text)

    print("Attempt two:")
    print(re.match(attempt_two, "4-5")) # Match: OK
    print(re.match(attempt_two, "2024-12-26")) # Doesn't match: OK
    new_text, _ = re.subn(attempt_two, r"\1 to \3", text) # Still incorrect
    print(new_text)


    Output:

    Attempt one:
    <re.Match object; span=(0, 3), match='4-5'>
    <re.Match object; span=(0, 7), match='2024-12'>

    2024 to 12-26
    4 to 5
    78 to 79

    Attempt two:
    <re.Match object; span=(0, 3), match='4-5'>
    None

    2024-12 to 26
    4 to 5
    78 to 79


    What regular expression can I use so that the substitution returns the following instead?

    2024-12-26
    4 to 5
    78 to 79


    (As my goal is to learn about regular expressions, I am not interested in workarounds such as matching the whitespace or newline after "12-26".)

    Continue reading...

Compartilhe esta Página