AltBlue has asked for the wisdom of the Perl Monks concerning the following question:

the problem: to extract strings from single quoted-like expressions...
my code (and some sample data):
#!/usr/bin/perl -Twl use strict; { local undef $/; my $string = <DATA>; # extract strings from 'usual' quotes: print 'MATCH: ', $2 while $string =~ /\bq([^\w{([])(.+?[^\\])\1/sg +; # extract strings from 'bracketted' quotes: for (( [ qw'{ }' ], [ qw'[ ]'], [ qw'( )' ] )) { print 'MATCH: ', $1 while $string =~ /\bq\Q$_->[0]\E(.+?[^\\])\Q$_->[1]\E/sg; } } __DATA__ my $km = q'BEGIN simple foo bar baz END'; my $kv = q#BEGIN foo bar \# baz END#; my $kk = q{BEGIN super foo bar banzai END}; my $kt = q{BEGIN super foo \{super\} bar banzai END};

the wisdom i'm looking for now is if i could unify that 2 scenarios above in a single one with a smarter regexp or smth... ofc, there still should be some kind of efficiency in the resulting regexp ... if possible ;-)

... i really wonder how my code would have looked like if i was supposed to match interpolated stuff like qq{ foo $bar{baz} :) } .. but that's another story to think of :)

--
AltBlue.

Replies are listed 'Best First'.
•Re: matching single-quoted-like strings (q{}, q//)
by merlyn (Sage) on Apr 03, 2003 at 22:09 UTC
      yes, Text::Balanced is supposed to be the right choice... but it seemed to me that i needed to do to much things before getting the results :( ... it would had be the best if it would have been as simple as something like:
      #!/usr/bin/perl -Twl use strict; use Text::Balanced qw(extract_quotelike); { local undef $/; my $string = <DATA>; my ($extracted, $remainder) = extract_quotelike($string); print $extracted; }
      .. but it doesn't work like this, looks like, as you said, more configuration is to be done. :(
      --
      AltBlue.
Re: matching single-quoted-like strings (q{}, q//)
by BrowserUk (Patriarch) on Apr 04, 2003 at 08:24 UTC

    I believe I got a version that runs a bit quicker this time:)

    #! perl -slw use strict; my %lookup; @lookup{map chr, 32..127}=map chr, 32..127; @lookup{'{', '(', '[', '<'} = ('}', ')', ']', '>'); my $string = do{ local $/; <DATA>}; print "Match:'$2'" while $string =~ m[\bq(.)(.+?(??{ $lookup{$1} }))]s +og; __DATA__ my $km = q'BEGIN simple foo bar baz END'; my $kv = q#BEGIN foo bar \# baz END#; my $kk = q{BEGIN super foo bar banzai END}; my $kt = q{BEGIN super foo \{super\} bar banzai END};

    Examine what is said, not who speaks.
    1) When a distinguished but elderly scientist states that something is possible, he is almost certainly right. When he states that something is impossible, he is very probably wrong.
    2) The only way of discovering the limits of the possible is to venture a little way past them into the impossible
    3) Any sufficiently advanced technology is indistinguishable from magic.
    Arthur C. Clarke.
Re: matching single-quoted-like strings (q{}, q//)
by BrowserUk (Patriarch) on Apr 04, 2003 at 05:48 UTC

    This seems reasonably efficient to work:/

    Update:I screwed up my benchmark, this is way slow compared to your method.

    #! perl -slw use strict; my %lookup = ('{'=>'}', '('=>')', '['=>']', '<'=>'>'); my $re_q = qr[\bq(.)(.*?)(?<!\\)(??{ $lookup{$1}||$1 })]so; my $string = do{ local $/; <DATA>}; print "Match:'$2'" while $string =~ m[$re_q]g; __DATA__ my $km = q'BEGIN simple foo bar baz END'; my $kv = q#BEGIN foo bar \# baz END#; my $kk = q{BEGIN super foo bar banzai END}; my $kt = q{BEGIN super foo \{super\} bar banzai END};

    Examine what is said, not who speaks.
    1) When a distinguished but elderly scientist states that something is possible, he is almost certainly right. When he states that something is impossible, he is very probably wrong.
    2) The only way of discovering the limits of the possible is to venture a little way past them into the impossible
    3) Any sufficiently advanced technology is indistinguishable from magic.
    Arthur C. Clarke.
Re: matching single-quoted-like strings (q{}, q//)
by dmitri (Priest) on Apr 03, 2003 at 22:39 UTC
    If all your data is of the form
    my $kt = q{BEGIN super foo};
    why not use eval()? First extract the name of the variable, then eval the string, and get the value of the string form that variable (you will need to no strict 'refs';).
      sorry, it's not all of that form. that is just a sample.
      + please remember that solution above it's working ok, i'm just looking for some more efficient approaches for it... yours looks very slow and 'painful' ;-)
      --
      AltBlue.