Just pass the sub your string, left delimiter, right delimeter, and an optional escape character.
As a side note, any regexophiles want to tell me how I can get that frickin' dot star out of there? I worked on it for hours, but that was the easiest solution :(
I remember seeing an earlier version of this in the form of while ( $str =~ s/\(([^)]+)\)/$1/g ){};It didn't allow for escaped characters and I can't remember where I found it. If any monks know the origin, I'd like to be able to credit the person who had the initial idea.
#!/usr/bin/perl -w use strict; my @strings = ( '(a(a(b)a)a)', # balanced '(a(a(b)a)a)a)', # too many right parens '(a(a(b)a\)a)a)', # balanced -- one right paren i +s escaped '(a(a\(a(a(b)a)a)', # unbalanced -- still have too +many left parens '(a(a\(a(b)a)a)' ); # balanced -- one left paren is + escaped foreach my $string ( @strings ) { my $balanced = balanced_delimiters( $string, "(", ")", "\\" ); print "Delimiters in $string are "; if ( $balanced ){ print "balanced.\n"; } else { print "not balanced.\n"; } } sub balanced_delimiters { # $escape is optional. If not supplied, no escape character will # be recognized. my $str = shift; my $left = quotemeta shift; my $right = quotemeta shift; my $escape = quotemeta shift; my $unescapedLeft = "(?<!$escape)$left"; my $unescapedRight = "(?<!$escape)$right"; my $middle = "."; # AAARRRRGGGGHHHH!!!! my $regex = "$unescapedLeft($middle*?)$unescapedRight"; while ($str =~ s/$regex/$1/gs){}; return $str =~ /$unescapedLeft|$unescapedRight/ ? 0 : 1; }
In reply to Determining if you have balanced delimiters by Ovid
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |