use strict; use warnings; use Text::Balanced qw(extract_bracketed); my $code = "sub blah {\n {}\n {}\n {}\n {}\n} and some other stuff sub another {\n}"; for my $end (find_ends($code)) { $code = substr($code, 0, $end) . "}" . substr($code, $end); } $code =~ s/sub/{sub/g; print "$code\n"; sub find_ends { local $_ = $_[0]; my @ends; while (/(sub\s+\S+\s*)(?={)/g) { () = extract_bracketed($_, '{}'); push @ends, pos; } return @ends; } #### sub find_ends { local $_ = $_[0]; my @ends; while (/(sub\s+\S+\s*{[^}]*})/g) { my $sub = $1; my $end; while ($sub) { my $open = $sub =~ tr/{/{/; my $close = $sub =~ tr/}/}/; if ($open > $close and /\G([^}]*})/g) { $sub .= $1; $end = $+[0]; } else { $end = $+[0]; last; } } push @ends, $end; } return @ends; } #### Benchmark: running rd, tb for at least 10 CPU seconds... rd: 9 wallclock secs (10.36 usr + 0.01 sys = 10.37 CPU) @ 29908.68/s (n=310153) tb: 11 wallclock secs (10.55 usr + 0.01 sys = 10.56 CPU) @ 5602.84/s (n=59166) Rate tb rd tb 5603/s -- -81% rd 29909/s 434% --