Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Things you think you'll never use.

by redlemon (Hermit)
on Jan 21, 2005 at 15:25 UTC ( [id://424001]=perlmeditation: print w/replies, xml ) Need Help??

You've read all the perldocs, tutorials and can quote verbatim from the Camel book. Even so you come across sections that don't make immediate sense or you'll think "I'm never going to use that!".

Like in perlre:

(??{ code }) ... This is a "postponed" regular subexpression. The "code" is evaluated at run time, at the moment this subexpression may match. The result of evaluation is considered as a regular expression and matched as if it were inserted instead of this construct.
"What would I use that for?"

Well, I came across a use yesterday. I find that B<some bold text> is easier to read than <b>some bold text</b>. Hence I wanted to use that on my website to make writing their web pages easier for my kids & wife. I didn't need the full POD syntax, so here it is: the (over)simplified one-line POD-2-HTML text marker.

1 while s!([BUI])(<+)\s*(.*?)\s*(??{'>' x length $2})!<$1>$3</$1>!;

It translates:

"B<<< I<< U<bold underlined text> >> >>>"
to
<B><I><U>bold underlined text</U></I></B>
(I know that in this case the HTML version is actually more readable than the bracketed version, but I just wanted to show that it handles stacked markup.)

Regex explanation:

my $pod2html = qr/ ([BUI]) # start of formatting pattern (<+) # collect opening braces \s*(.*?)\s* # collect text, without border space (??{'>' x length($2)}) # match same number of closing braces /x;
By using a hash lookup, this is easily expanded to include all kinds of translations.

Replies are listed 'Best First'.
Re: Things you think you'll never use.
by Jenda (Abbot) on Jan 21, 2005 at 23:14 UTC

    Why not something like this:

    $re = qr{ \< (?: (?> [^<>]+ ) # Non-parens without backtracking | (??{ $re }) # Group with matching parens )* \> }x; $s = "B<I<U<bold underlined text>>> and B<bold text>"; 1 while $s =~ s{([BUI])<([^<>]*(?:$re[^<>]*)*)>}{<$1>$2</$1>}g; print $s,"\n";

    Jenda
    We'd like to help you learn to help yourself
    Look around you, all you see are sympathetic eyes
    Stroll around the grounds until you feel at home
       -- P. Simon in Mrs. Robinson

I wonder...
by spurperl (Priest) on Jan 22, 2005 at 08:53 UTC
    How can we express the regular expression "some number of X's followed by the same number of Y's" in the most elegant way as a regex. I always thought it's quite problematic, until I saw your post.

      You mean something like:

      $s = "xxyyyyyy"; $s =~ m/((x+)(??{'y' x length($2)}))/ and print "$1\n";
      ? :-)

      Jenda
      We'd like to help you learn to help yourself
      Look around you, all you see are sympathetic eyes
      Stroll around the grounds until you feel at home
         -- P. Simon in Mrs. Robinson

        Yes this is exactly what I meant :-) But it's not the point of my post. The point was: this matching task is a real challenge for 'normal regexes'. This technique using ??{} is indeed a way to solve it. I wondered whether there are other ways, using more standard regex operators.

      If you want to match at least the same number, but it's okay to gobble up more:

      /(x+)(y+)(?(?{ length $2 < length $1 })(?!))/x

      Make it != if both matches must be the exact same length.

      Makeshifts last the longest.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://424001]
Approved by sschneid
Front-paged by thor
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (6)
As of 2024-03-28 14:05 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found