20.6.3. Discussion
As with almost everything else in Perl, there is more than one way to
do it. Each solution attempts to strike a balance between speed and
flexibility. Occasionally you may find HTML that's simple enough that
a trivial command-line call works:
% perl -pe 's/<[^>]*>//g' file
However, this breaks with files whose tags cross line boundaries,
like this:
<IMG SRC = "foo.gif"
ALT = "Flurp!">
So, you'll see people doing this instead:
% perl -0777 -pe 's/<[^>]*>//gs' file
or its scripted equivalent:
{
local $/; # temporary whole-file input mode
$html = <FILE>;
$html =~ s/<[^>]*>//gs;
}
But even that isn't good enough except for simplistic HTML without
any interesting bits in it. This approach fails for the following
examples of valid HTML (among many others):
<IMG SRC = "foo.gif" ALT = "A > B">
<!-- <A comment> -->
<script>if (a<b && a>c)</script>
<# Just data #>
<![INCLUDE CDATA [ >>>>>>>>>>>> ]]>
If HTML comments include other tags, those solutions would also break
on text like this:
<!-- This section commented out.
<B>You can't see me!</B>
-->
The only solution that works well here is to use the HTML parsing
routines from CPAN. The second code snippet shown in the Solution
demonstrates this better technique.
For more flexible parsing, subclass the HTML::Parser class and record
only the text elements you see:
package MyParser;
use HTML::Parser;
use HTML::Entities qw(decode_entities);
@ISA = qw(HTML::Parser);
sub text {
my($self, $text) = @_;
print decode_entities($text);
}
package main;
MyParser->new->parse_file(*F);