]> granicus.if.org Git - python/commitdiff
Closing issue1761.
authorAmaury Forgeot d'Arc <amauryfa@gmail.com>
Thu, 10 Jan 2008 21:59:42 +0000 (21:59 +0000)
committerAmaury Forgeot d'Arc <amauryfa@gmail.com>
Thu, 10 Jan 2008 21:59:42 +0000 (21:59 +0000)
Surprising behaviour of the "$" regexp: it matches the
end of the string, AND just before the newline at the end
of the string::

    re.sub('$', '#', 'foo\n') == 'foo#\n#'

Python is consistent with Perl and the pcre library, so
we just document it.
Guido prefers "\Z" to match only the end of the string.

Doc/library/re.rst
Lib/test/test_re.py

index 850e1f8727982940a7748cb74af094e472d1a04a..dd228356ec514bdf2a472781f4622b36e5822ef2 100644 (file)
@@ -98,7 +98,9 @@ The special characters are:
    string, and in :const:`MULTILINE` mode also matches before a newline.  ``foo``
    matches both 'foo' and 'foobar', while the regular expression ``foo$`` matches
    only 'foo'.  More interestingly, searching for ``foo.$`` in ``'foo1\nfoo2\n'``
-   matches 'foo2' normally, but 'foo1' in :const:`MULTILINE` mode.
+   matches 'foo2' normally, but 'foo1' in :const:`MULTILINE` mode; searching for
+   a single ``$`` in ``'foo\n'`` will find two (empty) matches: one just before
+   the newline, and one at the end of the string.
 
 ``'*'``
    Causes the resulting RE to match 0 or more repetitions of the preceding RE, as
index 3056ef35f386cf5dda8f8032d0981f4780d045e9..a2470cd6f27a78d949d8c2a7a120d8ec2cb84277 100644 (file)
@@ -671,6 +671,18 @@ class ReTests(unittest.TestCase):
         q = p.match(upper_char)
         self.assertNotEqual(q, None)
 
+    def test_dollar_matches_twice(self):
+        "$ matches the end of string, and just before the terminating \n"
+        pattern = re.compile('$')
+        self.assertEqual(pattern.sub('#', 'a\nb\n'), 'a\nb#\n#')
+        self.assertEqual(pattern.sub('#', 'a\nb\nc'), 'a\nb\nc#')
+        self.assertEqual(pattern.sub('#', '\n'), '#\n#')
+
+        pattern = re.compile('$', re.MULTILINE)
+        self.assertEqual(pattern.sub('#', 'a\nb\n' ), 'a#\nb#\n#' )
+        self.assertEqual(pattern.sub('#', 'a\nb\nc'), 'a#\nb#\nc#')
+        self.assertEqual(pattern.sub('#', '\n'), '#\n#')
+
 
 def run_re_tests():
     from test.re_tests import benchmarks, tests, SUCCEED, FAIL, SYNTAX_ERROR