Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

regsub problem

35 views
Skip to first unread message

Brian McGinity

unread,
May 30, 2012, 10:49:18 AM5/30/12
to
I am working on a regular expression and am having problems with
greedy matching.

Input looks like this:

<for z in (select * from dual) loop>

I would like to turn it into:

<%! zCurrentRow binary_integer; %> <% zCurrentRow:=0; for z in
(select * from dual) loop zCurrentRow:=zCurrentRow+1; %>

Which works with:
regsub -all {<for ([a-zA-z])([a-zA-z0-9_]*) in (.*) loop>} $str {<%!
\1\2CurrentRow binary_integer; %> <% \1\2CurrentRow:=0; for \1\2 in
\3 loop \1\2CurrentRow:=\1\2CurrentRow+1; %>} str

Problem is when more than 1 are present, the greedy match:

<for z in (select * from dual) loop>
<for zz in (select * from dual) loop>

<%! zCurrentRow binary_integer; %> <% zCurrentRow:=0; for z in
(select * from dual) loop>
<for zz in (select * from dual) loop zCurrentRow:=zCurrentRow+1;
%>

How can it know to stop at the first “loop>”?

I’ve tried non-greedy match qualifier: in (.*?) loop ### this
fails

I’ve tried positive lookahead:
regsub -all {<for ([a-zA-z])([a-zA-z0-9_]*) in (((?!loop).)*)} $str
{<%! \1\2currentRow binary_integer; %> <% \1\2currentRow:=0; for \1\2
in \3 loop \1\2currentRow:=\1\2currentRow+1;} str

which is very close:
<%! zcurrentRow binary_integer; %> <% zcurrentRow:=0; for z in
(select * from dual) loop zcurrentRow:=zcurrentRow+1;loop>
<%! zzcurrentRow binary_integer; %> <% zzcurrentRow:=0; for zz
in (select * from dual) loop zzcurrentRow:=zzcurrentRow+1;loop>

The problem is keeps the “loop>” at the end of the result.

Any suggestions with this one?






Aric Bills

unread,
May 30, 2012, 11:14:04 AM5/30/12
to
Try replacing (.*) with ([^>]*).

Yaroslav Schekin

unread,
May 30, 2012, 12:17:50 PM5/30/12
to
> I’ve tried non-greedy match qualifier:   in (.*?) loop
It seems that you need: {<for ([a-zA-z])([a-zA-z0-9_]*?) in (.*?)
loop>}

Also, watch this:

> regexp -about {<for ([a-zA-z])([a-zA-z0-9_]*) in (.*?) loop>}
3 {REG_UNONPOSIX REG_UUNPORT}

> regexp -about {<for ([a-zA-z])([a-zA-z0-9_]*?) in (.*?) loop>}
3 {REG_UNONPOSIX REG_UUNPORT REG_USHORTEST}

So, you didn't actually get shortest match first time. I suggest you
to read re_syntax man page about it.

WBR, Yaroslav Schekin.

Brian McGinity

unread,
May 30, 2012, 10:17:17 PM5/30/12
to
Thank you for helping with this.

> Try replacing (.*) with ([^>]*).

You're suggestion does work in this situation. The only thing when a
where clause is added it can create a problem:

<for z in (select * from dual where 1>2) loop>

A few things crop up which make this hard such as:

<for z in (select * from dual where (1>2 or 2=2) ) loop>

The input could be shorted without the word "loop" if it's easier:
<for z in (select * from dual where (1>2 or 2=2))>

I was thinking a negative lookahead might work...still having issues.


Aric Bills

unread,
May 31, 2012, 4:20:18 AM5/31/12
to
On May 30, 8:17 pm, Brian McGinity <br...@databaseknowledge.com>
wrote:
I don't believe your original post mentioned where clauses, but okay,
here's a regular expression that relies on negative lookahead:

{<for ([a-zA-Z][a-zA-Z0-9_]*) in (((?!loop).)*) loop>}

(NB: This expression consolidates your first two sets of parentheses
into a single one.)

By the way, don't eliminate the word "loop" from the input if you want
to process it with regular expressions.
0 new messages