This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author akira
Recipients Jason.Stumpf, akira, dbenbenn, docs@python, ezio.melotti, janzert, mrabarnett, r.david.murray, serhiy.storchaka
Date 2014-08-11.09:27:30
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1407749252.01.0.698615780468.issue19055@psf.upfronthosting.co.za>
In-reply-to
Content
tl;dr: added patch that clarifies Python re behavior. Please, review.

---

The documented behavior is not clear: why (a|ab)* is not equivalent to
(a|ab)(a|ab) for aba if the docs say "as many repetitions as are
possible"?

And it is not obvious (it is not the only possible behavior) e.g.,
POSIX [1] expects the longest match, PCRE [2] group may be atomic
(/possesive quantifiers), or there is ungreedy repetition:

  $ echo abac | grep -o '\(a\|ab\)* # Basic Regular Expression
  aba
  $ echo abac | grep -Eo '(a|ab)*' # Extended Regular Expression
  aba
  $ echo abac | grep -Po '(a|ab)*' # PCRE (like Python regexes)
  a
  a
  $ echo abac | grep -Po '(a|ab)(a|ab)' # PCRE (two repeats)
  aba
  $ echo abac | grep -Po '(a|ab)*c' # PCRE (re-eval to match the rest)
  abac
  $ echo abAc | grep -iPo '(a|ab)*+c' # PCRE (possessive quantifiers)
  Ac
  $ echo abac | grep -Po '(a|ab)*?' # PCRE (ungreedy, zero repeats)
  # matches nothing

where BREs, EREs are defined in [1] that says:

 If the pattern permits a variable number of matching characters and
 thus there is more than one such sequence starting at that point,
 *the longest such sequence is matched*.

and:

 Consistent with the whole match being the longest of the leftmost
 matches, each subpattern, from left to right, *shall match the
 longest possible string.*

Python regexes work like PCRE [2] that says:

  The matching process tries each alternative in turn, from left to
  right, and *the first one that succeeds is used*.  If the
  alternatives are within a subpattern (defined below), "succeeds"
  means matching the rest of the main pattern as well as the
  alternative in the subpattern.

It explains why (a|ab)* matches only a in aba ("the first one that
succeeds") and why at the same time (a|ab)*c matches abac: (a|ab) may
match ab in the latter case because the main pattern would fail
otherwise i.e., the advanced definition of "succeeds" is used:
""succeeds" means matching the rest of the main pattern ...".

Python docs [3] are similar but do not contain the "advanced"
"succeeds" definition:

   REs separated by ``'|'`` are tried from left to right. When one
   pattern completely matches, that branch is accepted. This means
   that once ``A`` matches, ``B`` will not be tested further, even if
   it would produce a longer overall match.  In other words, the
   ``'|'`` operator is never greedy.

It explains why (a|ab) matches a in aba. 

'*' behavior [2]:

   By default, the quantifiers are "greedy", that is, they match as
   much as possible (up to the maximum number of permitted times),
   without causing the rest of the pattern to fail.

and again Python docs [3] are similar:

  ``'*'`` Causes the resulting RE to match 0 or more repetitions of
   the preceding RE, as many repetitions as are possible.

It implies that (a|ab)* should be equivalent to (a|ab)(a|ab) to match
aba -- TWO REPETITIONS ARE MORE THAN ONE: "as many repetitions as are
possible". But it matches only 'a' i.e., it works as (a|ab) -- only
one repetition instead of two. In reality, (a|ab)* along works like a*.

I've uploaded a documentation patch that makes Python documentation
for '|' more similar to PCRE and clarifies '*' definition as R. David
Murray suggested in msg198126. Please, review.

[1] http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html
[2] http://man7.org/linux/man-pages/man3/pcrepattern.3.html
[3] http://hg.python.org/cpython/file/18a311479e8b/Doc/library/re.rst
History
Date User Action Args
2014-08-11 09:27:32akirasetrecipients: + akira, dbenbenn, ezio.melotti, mrabarnett, r.david.murray, docs@python, serhiy.storchaka, janzert, Jason.Stumpf
2014-08-11 09:27:32akirasetmessageid: <1407749252.01.0.698615780468.issue19055@psf.upfronthosting.co.za>
2014-08-11 09:27:31akiralinkissue19055 messages
2014-08-11 09:27:30akiracreate