#!/usr/bin/perl -w $|++; use strict; use Benchmark; # my first take - 'mine-less-lgnt' in test. sub getpropstr { local $_ = shift; my $level = shift || 0; if ( $level == -1 ) { /([^()]+)\)+$/; return $1 } while ( $level-- > 0) { chop; s/^[^(]+\(//; } return $_; } my @data = ; chomp @data; if(1) { for (@data) { print "$_\n"; print getpropstr( split ), "\n" ; print get_proparg( split ), "\n" ; print prop3( split ), "\n" ; print peeln( split ), "\n" ; } } my $count = 15000; timethese ( $count, { 'mine' => sub { for (@data) { prop3( split ); } }, 'mine-less-lgnt' => sub { for (@data) { getpropstr( split ); } }, 'his' => sub { for (@data) { get_proparg( split ); } }, 'other' => sub { for (@data) { peeln( split ); } }, } ); # BrowserUK's version 'other' in test sub peeln { local $_ = shift; my $n = shift || 0; my($c) = (tr[(][]); # warn 'Unbalanced parens' unless $o == $c; $n = $c if $n == -1; m[^ (?: .*? \( .*?){$n} (.+) (?: .*? \) .*?){$n} $]x; $1; } # original poster's (Fatvamp) 'his' in test sub get_proparg { my $propstr = shift; # get the property string my $level = shift || 0; # get the level we want to extract my $back = $propstr; # Initialize Return value (for case level=0) my $cnt; # initialize counter if($level == -1) { # special case, get the innermost argument $propstr =~ /\(([^\(\)]+)\)+/; $propstr = $1; } else { # get whatever argument $level indicates for($cnt = 0;$cnt<$level; $cnt++) { $propstr =~ /\((.+)\)/; $propstr = $1; } } return $propstr; } # my cleaner version 'mine' in test sub prop3 { my $str = shift; my $level = shift || 0; return $str unless $level; my @str = split(/[()]/, $str); splice @str, 0, $level; my $out = join('(', @str); $out .= ')' x ( @str - 1 ); return $out; } __END__ hello(what(is(this(all(about))))) 0 hello(what(is(this(all(about))))) 1 hello(what(is(this(all(about))))) 2 hello(what(is(this(all(about))))) 3 hello(what(is(this(all(about))))) 4 hello(what(is(this(all(about))))) 5 hello(what(is(this(all(about))))) -1