Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Re: Regex to pull out string within parenthesis that could contain parenthesis

by golux (Chaplain)
on Jul 09, 2018 at 15:45 UTC ( #1218169=note: print w/replies, xml ) Need Help??


in reply to Regex to pull out string within parenthesis that could contain parenthesis

Hi dpelican,

I think this will do what you need. It uses the recursive subpatterns described in the perlre documentation. By the time I finished getting my example working I saw that roboticus had already mentioned them. (I had never used the recursive regex method, so it was a good learning experience for me).

Edit:   Fixed some comments (specifically capture group numbering), and captured a little bit more.

Edit 2: Added output.

Edit 3: Allow keyword 'report' (somehow missed it the first time).

#!/usr/bin/perl # # References: # http://perldoc.perl.org/perlre.html (See section on 'PARNO') ## use strict; use warnings; use feature qw( say ); use Method::Signatures; ################## ## Main Program ## ################## my $str = 'private function convert_wa_date_strings(iv_beg string, iv_ +end string, iv_read_date date, iv_step char(6)) returns (date, date, +char(1))'; recursive_function_parsing_regex($str); ################# ## Subroutines ## ################# func recursive_function_parsing_regex($str) { my $re = qr{ ( # Paren group 1 -- full function (?: (private|public) # Paren group 2 -- optional 'private +' or 'public' \s+)? (function) # Paren group 3 -- required 'functio +n' keyword \s* # Optional space after 'function' (\w+) # Paren group 4 -- function name ( # Paren group 5 -- args in parens \( ( # Paren group 6 -- contents of paren +s (?: (?> [^()]+ ) # Non-parens without backtracking | (?5) # Recurse to start of paren group 5 )* ) \) ) (?: # Optional return value \s+ returns\s* ( # Paren group 7 -- return args in pa +rens \( ( # Paren group 8 -- return args (?: (?> [^()]+ ) # Non-parens without backtracking | (?7) # Recurse to start of paren group 7 )* ) \) ) )? ) }x; if ($str !~ /$re/) { say "No match for '$str'"; return; } my ($full, $pp, $func, $name, $par, $args, $ret, $rargs) = ($1, $2 + || "", $3, $4, $5, $6, $7 || "", $8 || ""); say "Match!"; say " \$full => '$full'"; # Full expression say " \$pp => '$pp'"; # Optional 'private' or 'public' k +eyword say " \$func => '$func'"; # 'function' keyword say " \$name => '$name'"; # Function name say " \$par => '$par'"; # Func args (in parens) say " \$args => '$args'"; # Func args (no parens) say " \$ret => '$ret'"; # Optional return args (in parens) say " \$rargs => '$rargs'"; # Optional return args (no parens) }

Result:

Match! $full => 'private function convert_wa_date_strings(iv_beg string, i +v_end string, iv_read_date date, iv_step char(6)) returns (date, date +, char(1))' $pp => 'private' $func => 'function' $name => 'convert_wa_date_strings' $par => '(iv_beg string, iv_end string, iv_read_date date, iv_step + char(6))' $args => 'iv_beg string, iv_end string, iv_read_date date, iv_step +char(6)' $ret => '(date, date, char(1))' $rargs => 'date, date, char(1)'
say  substr+lc crypt(qw $i3 SI$),4,5

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1218169]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (12)
As of 2020-11-24 10:35 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?