One minor difference is that
splitting this way removes the close-paragraph, but not the open-paragraph, so you need to remove it.
my @arr = grep {/\[tab\]/ and s/^<p>//} split /<\/p>/, $contents;
If you wanted to retain both tags, you could do so by
splitting on a lookbehind expression:
my @arr = grep /\[tab\]/, split /(?<=<\/p>)/, $contents;
You'd also retain the paragraph-close if you used it for
$/ and read the string as a file.
{
local $/ = '</p>';
open (STR, '<', \$contents) or die "Opening string: $!\n";
@arr = grep /^<p>/ && /\[tab\]/, <STR>;
print "read $_\n" for @arr;
}
But now I'm just getting silly.
Caution: Contents may have been coded under pressure.