Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4300019

Browse files
committed
Add re.fullmatch() function and regex.fullmatch() method, which anchor the
pattern at both ends of the string to match. Patch by Matthew Barnett. Closes #16203.
1 parent 57841dd commit 4300019

5 files changed

Lines changed: 156 additions & 45 deletions

File tree

Doc/library/re.rst

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,16 @@ form.
584584
instead (see also :ref:`search-vs-match`).
585585

586586

587+
.. function:: fullmatch(pattern, string, flags=0)
588+
589+
If the whole *string* matches the regular expression *pattern*, return a
590+
corresponding :ref:`match object <match-objects>`. Return ``None`` if the
591+
string does not match the pattern; note that this is different from a
592+
zero-length match.
593+
594+
.. versionadded:: 3.4
595+
596+
587597
.. function:: split(pattern, string, maxsplit=0, flags=0)
588598

589599
Split *string* by the occurrences of *pattern*. If capturing parentheses are
@@ -778,6 +788,24 @@ attributes:
778788
:meth:`~regex.search` instead (see also :ref:`search-vs-match`).
779789

780790

791+
.. method:: regex.fullmatch(string[, pos[, endpos]])
792+
793+
If the whole *string* matches this regular expression, return a corresponding
794+
:ref:`match object <match-objects>`. Return ``None`` if the string does not
795+
match the pattern; note that this is different from a zero-length match.
796+
797+
The optional *pos* and *endpos* parameters have the same meaning as for the
798+
:meth:`~regex.search` method.
799+
800+
>>> pattern = re.compile("o[gh]")
801+
>>> pattern.fullmatch("dog") # No match as "o" is not at the start of "dog".
802+
>>> pattern.fullmatch("ogre") # No match as not the full string matches.
803+
>>> pattern.fullmatch("doggie", 1, 3) # Matches within given limits.
804+
<_sre.SRE_Match object at ...>
805+
806+
.. versionadded:: 3.4
807+
808+
781809
.. method:: regex.split(string, maxsplit=0)
782810

783811
Identical to the :func:`split` function, using the compiled pattern.

Lib/re.py

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -85,16 +85,17 @@
8585
\\ Matches a literal backslash.
8686
8787
This module exports the following functions:
88-
match Match a regular expression pattern to the beginning of a string.
89-
search Search a string for the presence of a pattern.
90-
sub Substitute occurrences of a pattern found in a string.
91-
subn Same as sub, but also return the number of substitutions made.
92-
split Split a string by the occurrences of a pattern.
93-
findall Find all occurrences of a pattern in a string.
94-
finditer Return an iterator yielding a match object for each match.
95-
compile Compile a pattern into a RegexObject.
96-
purge Clear the regular expression cache.
97-
escape Backslash all non-alphanumerics in a string.
88+
match Match a regular expression pattern to the beginning of a string.
89+
fullmatch Match a regular expression pattern to all of a string.
90+
search Search a string for the presence of a pattern.
91+
sub Substitute occurrences of a pattern found in a string.
92+
subn Same as sub, but also return the number of substitutions made.
93+
split Split a string by the occurrences of a pattern.
94+
findall Find all occurrences of a pattern in a string.
95+
finditer Return an iterator yielding a match object for each match.
96+
compile Compile a pattern into a RegexObject.
97+
purge Clear the regular expression cache.
98+
escape Backslash all non-alphanumerics in a string.
9899
99100
Some of the functions in this module takes flags as optional parameters:
100101
A ASCII For string patterns, make \w, \W, \b, \B, \d, \D
@@ -123,7 +124,7 @@
123124
import sre_parse
124125

125126
# public symbols
126-
__all__ = [ "match", "search", "sub", "subn", "split", "findall",
127+
__all__ = [ "match", "fullmatch", "search", "sub", "subn", "split", "findall",
127128
"compile", "purge", "template", "escape", "A", "I", "L", "M", "S", "X",
128129
"U", "ASCII", "IGNORECASE", "LOCALE", "MULTILINE", "DOTALL", "VERBOSE",
129130
"UNICODE", "error" ]
@@ -154,6 +155,11 @@ def match(pattern, string, flags=0):
154155
a match object, or None if no match was found."""
155156
return _compile(pattern, flags).match(string)
156157

158+
def fullmatch(pattern, string, flags=0):
159+
"""Try to apply the pattern to all of the string, returning
160+
a match object, or None if no match was found."""
161+
return _compile(pattern, flags).fullmatch(string)
162+
157163
def search(pattern, string, flags=0):
158164
"""Scan through string looking for a match to the pattern, returning
159165
a match object, or None if no match was found."""

Lib/test/test_re.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1061,6 +1061,30 @@ def test_bug_2537(self):
10611061
self.assertEqual(m.group(1), "")
10621062
self.assertEqual(m.group(2), "y")
10631063

1064+
def test_fullmatch(self):
1065+
# Issue 16203: Proposal: add re.fullmatch() method.
1066+
self.assertEqual(re.fullmatch(r"a", "a").span(), (0, 1))
1067+
self.assertEqual(re.fullmatch(r"a|ab", "ab").span(), (0, 2))
1068+
self.assertEqual(re.fullmatch(r".*?$", "abc").span(), (0, 3))
1069+
self.assertEqual(re.fullmatch(r".*?", "abc").span(), (0, 3))
1070+
self.assertEqual(re.fullmatch(r"a.*?b", "ab").span(), (0, 2))
1071+
self.assertEqual(re.fullmatch(r"a.*?b", "abb").span(), (0, 3))
1072+
self.assertEqual(re.fullmatch(r"a.*?b", "axxb").span(), (0, 4))
1073+
self.assertEqual(re.fullmatch(r"abc$", "abc\n"), None)
1074+
self.assertEqual(re.fullmatch(r"abc\Z", "abc\n"), None)
1075+
self.assertEqual(re.fullmatch(r"(?m)abc$", "abc\n"), None)
1076+
self.assertEqual(re.fullmatch(r"ab(?=c)cd", "abcd").span(), (0, 4))
1077+
self.assertEqual(re.fullmatch(r"ab(?<=b)cd", "abcd").span(), (0, 4))
1078+
self.assertEqual(re.fullmatch(r"(?=a|ab)ab", "ab").span(), (0, 2))
1079+
1080+
self.assertEqual(
1081+
re.compile(r"bc").fullmatch("abcd", pos=1, endpos=3).span(), (1, 3))
1082+
self.assertEqual(
1083+
re.compile(r".*?$").fullmatch("abcd", pos=1, endpos=3).span(), (1, 3))
1084+
self.assertEqual(
1085+
re.compile(r".*?").fullmatch("abcd", pos=1, endpos=3).span(), (1, 3))
1086+
1087+
10641088
def run_re_tests():
10651089
from test.re_tests import tests, SUCCEED, FAIL, SYNTAX_ERROR
10661090
if verbose:

0 commit comments

Comments
 (0)