"can I parse this HTML in a single regex". And the answer is yes!
... with a BIG emphasis on this HTML. HTML is a beast to parse correctly, due to its inheritance from SGML, and due to the error correction / guessing algorithms used in most browsers. Simple regular expressions may work as long as the HTML has a well-known format and does not use too many SGML or encoding tricks.
Just yesterday, I stubled over this nice piece of valid(!) HTML, hand-crafted to defeat most simple-minded string parsers and regular expressions:
<h1>My-IP-Service</h1> <h1 class="myip"><!--- > A comment about the abuse of their service they want to prevent ... <a href="/netze/tools/whois-abfrage/?rm=whois_formular">nicht ermittel +bar</a> <a href="/netze/tools/whois-abfrage/?rm=whois_formular">127.0.0.1</a> <a href="/netze/tools/whois-abfrage/?rm=whois_formular">198.18.0.15</a +> < --><a href="/netze/tools/whois-abfrage/?rm=whois_formular">9<!-- + >226.180.195.155 < -->2<!-- > 253.159.244.9 < -->.<!-- > 253.239.61.182< -->2<!-- >230.121.254.208 < -->2<!-- > 251.168.157.152 < -->4<!-- > 254.121.189.15< -->.<!-- > 237.24.153.213< -->8<!-- >246.217.119.248 < -->.<!-- > 245.167.107.28 < -->1<!-- >226.204.198.25 < -->1<!-- > 233.167.179.189 < -->7<!-- > 228.193.179.191< --></a></h1>
(From: http://www.heise.de/netze/tools/ip)
Returning the correct IP address (92.224.8.117 in this case) from this piece of HTML is not impossible, and with enough effort, someone may be able to write a regexp that does the job for this special obfuscation. But with HTML::Parser, it is essentially a no-brainer requiring about 10 lines of code (Sorry, Heise ...). And unless the author finds a way to confuse HTML::Parser without breaking browsers, it will not fail when the author modifies the obfuscation. (Well, changing the H1 tag or its class attribute would break this special implementation.)
#!/usr/bin/perl -w use strict; use LWP::Simple; use HTML::Parser; my $ip=''; my $wanted=0; HTML::Parser->new( api_version => 3, start_h => [sub { $wanted=1 if ($_[0] eq 'h1') && ($_[1]->{'class' +} eq 'myip') }, 'tagname,attr'], end_h => [sub { $wanted=0 if $_[0] eq 'h1' }, 'tagname'], text_h => [sub { $ip.=$_[0] if $wanted }, 'dtext'], )->parse(get('http://www.heise.de/netze/tools/ip')); print "$ip\n";
So, DON'T use regular expressions to parse HTML or XML. Except perhaps in very special cases where you control how the HTML/XML is generated.
Alexander
In reply to Re^2: Split/Match Question
by afoken
in thread Split/Match Question
by esmadmin
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |