I did bother... and IMVHO I think it could help out the OP.
Ok, I didn't post *the* solution, but you probably also know there's always more than one way to solve a problem in Perl. This one isn't maybe the easiest, or fastest, or most elegant one... but I still think it could help.
btw: you can always downvote me if you don't like what I said ;)
pussy ass code to proof (I hate proofing) I did bother:
#!/usr/bin/perl
use Text::Balanced qw{extract_multiple extract_bracketed extract_delim
+ited extract_tagged};
my $text = '<p>paragraph<b>BOLD text</p><a href=">>>>">link text</a><d
+iv><p>Some new text <b>in bold and <i>cursive</b></p></div><p>test</p
+>';
local $\ = $/;
print "text= $text";
my @stack;
my $error;
@fields = extract_multiple($text,
[
{ Tag => sub { extract_tagged($_[0]) } },
{ Brack => sub { extract_bracketed($_[0],'<>')
+ } },
],
undef,
0
);
foreach my $elem (@fields){
if(ref( $elem ) eq 'Tag'){
(print_stack(), $error--) if defined $error;
print "OK Tag: ".$$elem;
}
elsif(ref $elem eq 'Brack'){
my ($otag) = $$elem =~ m#<([a-zA-Z0-9]+)>#;
my ($ctag) = $$elem =~ m#</([a-zA-Z0-9]+)>#;
add_to_stack($otag) if defined $otag;
remove_from_stack($ctag) if defined $ctag;
}
else {
$error = 1;
}
}
sub print_stack {
foreach my $tag (@stack){
print "not properly closed: ". $tag if defined $tag;
}
}
sub add_to_stack {
push @stack, shift;
}
sub remove_from_stack {
my $tag = shift;
foreach my $c (reverse 0 .. @stack) {
delete $stack[$c] if($stack[$c] eq $tag )
}
}
Gives as output:
text= <p>paragraph<b>BOLD text</p><a href=">>>>">link text</a><div><p>
+Some new text <b>in bold and <i>cursive</b></p></div><p>test</p>
not properly closed: b
OK Tag: <a href=">>>>">link text</a>
not properly closed: i
OK Tag: <p>test</p>
to ask a question is a moment of shame
to remain ignorant is a lifelong shame