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
^^ ^^ ^^^
\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
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)'