Home > Enterprise >  regular expression to match an odd number in a string
regular expression to match an odd number in a string

Time:10-19

I'm trying to use a regular expression to match only odd numbers in a string. What I'm thinking is to detect whether the last digit of the number is odd or not, but now I can only find the first (n-1) digits except for the last one.

For example, the following code works for the odd number 13, which is perfect! But when it turns to 132, the code still returns 13, which definitely fails. So, how can I manipulate the code and let it work for all numbers (no matter how large it is) ending with odd digits? Thank you!

match= '(\s*\d*[13579]\s*)'
print(re.search(match, "The number 13 matches")) #<re.Match object; span=(10, 14), match=' 13 '>
print(re.search(match, "The number 132 matches")) #<re.Match object; span=(10, 13), match=' 13'>

CodePudding user response:

You can match

\d (?!\d)(?<=[13579])

23 132 87 74 101
^^     ^^    ^^^

Demo

\d       # match one or more digits
(?!      # begin negative lookahead
  \d     # match a digit
)        # end negative lookahead
(?<=     # begin positive lookbehind
[13579]  # match an odd digit
)        # end positive lookbehind

(?!\d) could be replaced by (?=\D|$), a positive lookahead that asserts that the match is followed by a non-digit or is at the end of the string.

CodePudding user response:

You can use the regex, \d [13579](?=\s|$) which can be explained as

  • \d : One or more digits
  • [13579] : 1, 3, 5, 7, or 9
  • (?=\s|$) : Positive lookahead assertion for whitespace or end of line

Demo:

import re
match= '\d [13579](?=\s|$)'
print(re.search(match, "The number 13 matches")) 
print(re.search(match, "The number 132 matches"))

Output:

<re.Match object; span=(11, 13), match='13'>
None

CodePudding user response:

Use

(?<!\d)\d*[13579](?!\d)

See regex proof.

EXPLANATION

--------------------------------------------------------------------------------
  (?<!                     look behind to see if there is not:
--------------------------------------------------------------------------------
    \d                       digits (0-9)
--------------------------------------------------------------------------------
  )                        end of look-behind
--------------------------------------------------------------------------------
  \d*                      digits (0-9) (0 or more times (matching
                           the most amount possible))
--------------------------------------------------------------------------------
  [13579]                  any character of: '1', '3', '5', '7', '9'
--------------------------------------------------------------------------------
  (?!                      look ahead to see if there is not:
--------------------------------------------------------------------------------
    \d                       digits (0-9)
--------------------------------------------------------------------------------
  )                        end of look-ahead

Python code:

import re
regex = r"(?<!\d)\d*[13579](?!\d)"
test_str = "The number 13 matches"
matches = re.search(regex, test_str)
if matches is not None:
    print(matches.group())

Results: 13.

Also word boundaries could be used:

\b\d*[13579]\b

CodePudding user response:

You could do a non-greedy search of decimals \d*? followed by an odd number [13579] and a word boundary \b. Put it together

import re

tests = [("The number 13 matches", True), 
    ("The number 132 matches", False)]

for test, is_match in tests:
    match = re.search(r"\d*?[13579]\b", test)
    print(repr(test), bool(match), "PASS" if bool(match) == is_match else "FAIL")       

CodePudding user response:

Use a look ahead to check that the odd digit is not followed by another digit:

match = '\d*[13579](?!\d)'
  • Related