473,386 Members | 1,763 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

re.match -- not greedy?

the '*' and '+' don't seem to be greedy.. they will consume less in
order to match a string:
>>import re;re.match('(a+)(ab)','aaab').groups()
('aa', 'ab')

this is the sort of behaviour i'd expect from
'(a+?)(ab)'

a+ should greedily consume a's at the expense of the string not matching

in real life, i am trying to match #defines:
>>re.match( '#define ([A-Za-z0-9_]+)([^(])', '#define
abc(d)').groups()
('ab', 'c')

i want this example to fail because the first character after a string
of letters is a '('
i want to match only #defines without parameters.

so what's the definition of greedy?

(pls copy me on responses)

ta,
jack
Nov 19 '06 #1
6 2688
EXI-Andrews, Jack wrote:
the '*' and '+' don't seem to be greedy.. they will consume less in
order to match a string:
>import re;re.match('(a+)(ab)','aaab').groups()
('aa', 'ab')

this is the sort of behaviour i'd expect from
'(a+?)(ab)'

a+ should greedily consume a's at the expense of the string not matching
It's called backtracking. If a match fails, the regexp engine
recursively unwinds some of the greedy matching and tries again.
in real life, i am trying to match #defines:
>re.match( '#define ([A-Za-z0-9_]+)([^(])', '#define
abc(d)').groups()
('ab', 'c')

i want this example to fail because the first character after a string
of letters is a '('
i want to match only #defines without parameters.
Probably the easiest thing to do is to attempt to match zero or one
opening parentheses, and bail out if it did end up matching the
parenthesis.

m = re.match(r"#define ([A-Za-z0-9_]+)(\(?)","#define abc(d)")
if m and m.groups(2) != "(":
...

(BTW, it's good practice to use a raw strings for the regular
expressions as I did.)
so what's the definition of greedy?
It means match as much you can *while getting a match*.

Just remember regexp parsing is not a one way street: if it hits a dead
end, it'll go back and try another path. In fact, greediness usually
doesn't affect *whether* a regexp matches; it only affects the
groupings. I'm suddenly curious if there are any cases at all where
greediness changes whether it finds a match.
(pls copy me on responses)
Ah, too bad you won't see it then....
Carl Banks

Nov 19 '06 #2
* Carl Banks wrote:
I'm suddenly curious if there are any cases at all where
greediness changes whether it finds a match.
nope, per definitionem ;-)

greedy := longest leftmost match

nd
--
die (eval q-qq[Just Another Perl Hacker
]
;-)
# André Malo, <http://www.perlig.de/#
Nov 20 '06 #3
Carl Banks wrote:
EXI-Andrews, Jack wrote:
>the '*' and '+' don't seem to be greedy.. they will consume less in
order to match a string:
>>>>import re;re.match('(a+)(ab)','aaab').groups()
('aa', 'ab')

this is the sort of behaviour i'd expect from
'(a+?)(ab)'

a+ should greedily consume a's at the expense of the string not matching

It's called backtracking. If a match fails, the regexp engine
recursively unwinds some of the greedy matching and tries again.
>in real life, i am trying to match #defines:
>>>>re.match( '#define ([A-Za-z0-9_]+)([^(])', '#define
abc(d)').groups()
('ab', 'c')

i want this example to fail because the first character after a string
of letters is a '('
i want to match only #defines without parameters.

Probably the easiest thing to do is to attempt to match zero or one
opening parentheses, and bail out if it did end up matching the
parenthesis.

m = re.match(r"#define ([A-Za-z0-9_]+)(\(?)","#define abc(d)")
if m and m.groups(2) != "(":
...

(BTW, it's good practice to use a raw strings for the regular
expressions as I did.)
Another way that seems clearer to me is to use negative lookahead
assertions.
>>>defPatt = re.compile(r'#define\s+(\w+)\b(?!\()')
defPatt.match("#define abc(x)")
defPatt.match("#define foo_BarBaz")
<_sre.SRE_Match object at 0xb7dd5820>
>>defPatt.match("#define foo_BarBaz").groups()
('foo_BarBaz',)

In general '\w' is the same as [A-Za-z0-9_]

There are other considerations too... I don't know if

#define abc (x)

But the main thing here is the use of '\b' to require there to be a word
boundary at the end your match and a (?!\() to require that the match is
not followed by a '('

see http://docs.python.org/lib/re-syntax.html

noah

>so what's the definition of greedy?

It means match as much you can *while getting a match*.

Just remember regexp parsing is not a one way street: if it hits a dead
end, it'll go back and try another path. In fact, greediness usually
doesn't affect *whether* a regexp matches; it only affects the
groupings. I'm suddenly curious if there are any cases at all where
greediness changes whether it finds a match.
>(pls copy me on responses)

Ah, too bad you won't see it then....
Carl Banks
Nov 20 '06 #4
"EXI-Andrews, Jack" <Ja**********@boeing.comwrote in message
news:ma**************************************@pyth on.org...

in real life, i am trying to match #defines:
>>re.match( '#define ([A-Za-z0-9_]+)([^(])', '#define
abc(d)').groups()
('ab', 'c')

i want this example to fail because the first character after a string
of letters is a '('
i want to match only #defines without parameters.
>
Here's a pyparsing grammar that matches your #defines as you describe (skip
over #defines with parameters), and also skips over ones that are commented
out. It also parses the rest of the definition line (definitions with
end-of-line '\' continuations not included in this sample):

from pyparsing import *
defWithoutParen = "#define" + \
Word(alphas,alphanums+"_") + \
~Literal("(").leaveWhitespace() + \
Optional(restOfLine)
defWithoutParen.ignore(cStyleComment)

Here's sample code showing how to use this grammar:

sample = """
#define PI 3.141592
#define SUCCESS (href==1)
#define MIN(a,b) a<b ? a : b
#define E 2.71828
/*
#define lockMutex mockLockMutex
*/
#define WIN32
"""
matches = defWithoutParen.searchString(sample)
for m in matches:
print m

Prints out:
['#define', 'PI', '3.141592']
['#define', 'SUCCESS', '(href==1)']
['#define', 'E', '2.71828']
['#define', 'WIN32', '']

-- Paul
Nov 20 '06 #5
Carl Banks wrote:
I'm suddenly curious if there are any cases at all where greediness
changes whether it finds a match.
the "|" operator picks the leftmost subpattern that matches in any way,
so the *overall* greediness of a Python RE can vary. e.g.

re.match("(ab?a|a.a+)", "abaaaaaaaa")

matches three characters, not ten.

</F>

Nov 20 '06 #6
Ant

EXI-Andrews, Jack wrote:
the '*' and '+' don't seem to be greedy.. they will consume less in
order to match a string:
>import re;re.match('(a+)(ab)','aaab').groups()
('aa', 'ab')

this is the sort of behaviour i'd expect from
'(a+?)(ab)'

a+ should greedily consume a's at the expense of the string not matching
They are greedy - they consume as much as possible *without*
sacrificing the match.

You are thinking I think of possessive quantifiers, such as found in
Java, which *will* match as much as possible even if doing so causes
the match to fail. This would be written:

re.match('(a++)(ab)','aaab')

Python doesn't support these possessive quantifiers.

Nov 22 '06 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: meltedown | last post by:
I want to match a table and also capture the parts before and after the table: preg_match_all("|(.*)(<table.*table>)(.*)|",$text, $parts); But of course it doesn't work, presumably because the...
12
by: Joerg Schuster | last post by:
Hello, The program given below returns the lines: a ab Is there a way to use python regular expressions such that the program would return the following lines?
3
by: bdwise | last post by:
I have this in my body tag: something();something(); document.thisForm.textBox1.focus();something(); And I want to find a part between the semicolons that ends in focus() and remove the...
6
by: likong | last post by:
Hi, Any idea about how to write a regular expression that matches a substring xxx as long as the string does NOT contain substring yyy? Thanks. Kong
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.