THIS IS OUTSIDE (THIS IS INSIDE) (inside) outside before (within) after before (within) between (within again) after b ((nested)) a before (within (nested)) after This one hangs (with an unmatched open This one has () an empty pair This opens (with one)) and double closes this is the last (really) one #### #!perl use strict; use warnings; use 5.12.0; my $cleanup = 1; while ( <> ) { chomp; s/\(+.*?\)+//g; y/ / /s, s/^\s|\s$// if $cleanup; say; } #### THIS IS OUTSIDE outside before after before between after b a before after This one hangs (with an unmatched open This one has an empty pair This opens and double closes this is the last one #### #!perl use strict; use warnings; use 5.12.0; while ( <> ) { chomp; my $str = ''; my @parts = split //; my $inside = 0; for ( @parts ) { /\(/ && $inside++ && next; /\)/ && $inside-- && next; $str .= $_ unless $inside; } say $str; } #### THIS IS OUTSIDE outside before after before between after b a before after This one hangs This one has an empty pair This opens this is the last one #### #!perl use strict; use warnings; use 5.12.0; while ( my $str = <> ) { chomp $str; my $extract = join '|', map { "\Q$_\E" } ( $str =~ m/(\(+.*?\)+)/g ); say join '', split /$extract/, $str; } #### #!perl use strict; use warnings; use 5.12.0; my $inside = 0; while ( <> ) { chomp; my $str = ''; my @parts = split //; $inside = 0; for ( @parts ) { 0 > $inside && $inside++ && warn "WARNING: extra close on line $.\n"; /\(/ && $inside++ && next; /\)/ && $inside-- && next; $str .= $_ unless $inside > 0; } warn "WARNING: Unclosed parenthetical on line $.\n" if $inside; say $str; } #### THIS IS OUTSIDE outside before after before between after b a before after WARNING: Unclosed parenthetical on line 7 This one hangs This one has an empty pair WARNING: extra close on line 9 This opens ) and double closes this is the last one