Ответ 1
РЕЗЮМЕ
Использование шаблонов на небольших, ограниченных фрагментах достаточно четко определенных фрагментов HTML является быстрым и легким. Но использование их во всем документе, содержащем полностью общий, открытый HTML-код непредвиденных причуд, теоретически возможно, на практике слишком много, по сравнению с использованием какого-то парсера elses, который уже был написан для этой прямой цели. См. Также этот ответ для более общей дискуссии об использовании шаблонов в XML или HTML.
Наивное решение Regex
Youve попросил решение для регулярных выражений, поэтому я предоставил вам такое.
#!/usr/bin/perl
use 5.10.0;
use strict;
use warnings;
$/ = undef;
$_ = <DATA>; # read all input
while (m{ < \s* img [^>]* src \s* = \s* ['"]? ([^<>'"]+) }gsix) {
print "IMG SRC=$1\n";
}
while (m{ < \s* a [^>]* href \s* = \s* ['"]? ([^<>'"]+) }gsix) {
print "A HREF=$1\n";
}
while (m{ < \s* strong [^>]* > (.*?) < \s* / \s* strong \s* > }gsix) {
print "STRONG=$1\n";
}
__END__
<td class="MODULE_PRODUCTS_CELL" align="center" valign="top" height="100">
<table width="100" summary="products">
<tr>
<td align="center" height="75">
<a href="/collections.php?prod_id=50">
<img src="files/products_categories50_t.txt" border="0" alt="products" />
</a>
<br/>
</td>
</tr>
<tr>
<td align="center">
<a href="/collections.php?prod_id=50">
<strong>Buffer</strong><br />
</a>
<td>
</tr>
</table>
</td>
Эта программа при запуске производит этот вывод:
IMG SRC=files/products_categories50_t.txt
A HREF=/collections.php?prod_id=50
A HREF=/collections.php?prod_id=50
STRONG=Buffer
Если вы совершенно уверены, что работаете с конкретным образцом HTML, который вы ему пожелаете, тогда обязательно используйте его. Обратите внимание на несколько вещей, которые я делаю, которых вы не делали. Один из них не имеет дело с HTML-строкой за раз. Это практически никогда не работает.
Однако подобные решения работают только на крайне ограниченных формах допустимого HTML. Вы можете использовать его только тогда, когда можете гарантировать, что HTML, с которым вы работаете, действительно выглядит так, как вы ожидаете.
Проблема в том, что она довольно часто выглядит не совсем аккуратно и аккуратно. В этих ситуациях вам настоятельно рекомендуется использовать класс разбора HTML. Однако никто, кажется, не показал вам код для этого. Это не очень полезно.
Решение Regex уровня мастера
И я тоже буду одним из них. Потому что я собираюсь показать вам более общее решение для приближения к тому, что, как я полагаю, относится к вам, но в отличие от других, кто когда-либо публикует Stack Overflow, Im собирается использовать регулярные выражения, чтобы сделать это, , чтобы показать вам, что это может быть сделано, но вы не хотите делать это следующим образом:
#!/usr/bin/perl
use 5.10.0;
use strict;
use warnings;
$/ = undef;
$_ = <DATA>; # read all input
our(
$RX_SUBS,
$tag_template_rx,
$script_tag_rx,
$style_tag_rx,
$strong_tag_rx,
$a_tag_rx,
$img_tag_rx,
);
# strip stuff we aren't supposed to look at
s{ <! DOCTYPE .*? > }{}sx;
s{ <! \[ CDATA \[ .*? \]\] > }{}gsx;
s{ $style_tag_rx .*? < (?&WS) / (?&WS) style (?&WS) > }{}gsix;
s{ $script_tag_rx .*? < (?&WS) / (?&WS) script (?&WS) > }{}gsix;
s{ <!-- .*? --> }{}gsx;
while (/$img_tag_rx/g) {
my $tag = $+{TAG};
printf "IMG tag at %d: %s\n", pos(), $tag;
while ($tag =~
m{
$RX_SUBS
\b src (?&WS) = (?&WS)
(?<VALUE>
(?: (?"ed_value) | (?&unquoted_value) )
)
}gsix)
{
my $value = dequote($+{VALUE});
print "\tSRC is $value\n";
}
}
while (/$a_tag_rx/g) {
my $tag = $+{TAG};
printf "A tag at %d: %s\n", pos(), $tag;
while ($tag =~
m{
$RX_SUBS
\b href (?&WS) = (?&WS)
(?<VALUE>
(?: (?"ed_value) | (?&unquoted_value) )
)
}gsix)
{
my $value = dequote($+{VALUE});
print "\tHREF is $value\n";
}
}
while (m{
$strong_tag_rx (?&WS)
(?<BODY> .*? ) (?&WS)
< (?&WS) / (?&WS) strong (?&WS) >
}gsix)
{
my ($tag, $body) = @+{ qw< TAG BODY > };
printf "STRONG tag at %d: %s\n\tBODY=%s\n",
pos(), $+{TAG}, $+{BODY};
}
exit;
sub dequote {
my $string = shift();
$string =~ s{
^
(?<quote> ["'] )
(?<BODY>
(?: (?! \k<quote> ) . ) *
)
\k<quote>
$
}{$+{BODY}}gsx;
return $string;
}
sub load_patterns {
$RX_SUBS = qr{ (?(DEFINE)
(?<any_attribute>
\b \w+
(?&WS) = (?&WS)
(?:
(?"ed_value)
| (?&unquoted_value)
)
)
(?<unquoted_value>
(?&unwhite_chunk)
)
(?<quoted_value>
(?<quote> ["'] )
(?: (?! \k<quote> ) . ) *
\k<quote>
)
(?<unwhite_chunk>
(?:
# (?! [<>'"] )
(?! > )
\S
) +
)
(?<WS> \s * )
(?<end_tag>
(?&html_end_tag)
| (?&xhtml_end_tag)
)
(?<html_end_tag> > )
(?<xhtml_end_tag> / > )
) # end DEFINE
}six;
my $_TAG_SUBS = $RX_SUBS . q{ (?(DEFINE)
(?<attributes>
(?:
(?&WS)
(?&one_attribute)
) *
)
(?<one_attribute>
(?= (?&legal_attribute) )
(?&any_attribute)
)
(?<optional_attribute>
(?&permitted_attribute)
| (?&deprecated_attribute)
)
(?<legal_attribute>
(?: (?&required_attribute)
| (?&optional_attribute)
| (?&standard_attribute)
| (?&event_attribute)
# for LEGAL parse only, comment out next line
| (?&illegal_attribute)
)
)
(?<optional_attribute>
(?&permitted_attribute)
| (?&deprecated_attribute)
)
(?<illegal_attribute> \b \w+ \b )
(?<tag>
(?&start_tag)
(?&WS)
(?&attributes)
(?&WS)
(?&end_tag)
)
) # end DEFINE
}; # this is a q tag, not a qr
$tag_template_rx = qr{
$_TAG_SUBS
(?<TAG> (?&XXX_tag) )
(?(DEFINE)
(?<XXX_tag> (?&tag) )
(?<start_tag> < (?&WS) XXX \b )
(?<required_attribute> (*FAIL) )
(?<standard_attribute> (*FAIL) )
(?<event_attribute> (*FAIL) )
(?<permitted_attribute> (*FAIL) )
(?<deprecated_attribute> (*FAIL) )
) # end DEFINE
}six;
$script_tag_rx = qr{
$_TAG_SUBS
(?<TAG> (?&script_tag) )
(?(DEFINE)
(?<script_tag> (?&tag) )
(?<start_tag> < (?&WS) style \b )
(?<required_attribute> type )
(?<permitted_attribute>
charset
| defer
| src
| xml:space
)
(?<standard_attribute> (*FAIL) )
(?<event_attribute> (*FAIL) )
(?<deprecated_attribute> (*FAIL) )
) # end DEFINE
}six;
$style_tag_rx = qr{
$_TAG_SUBS
(?<TAG> (?&style_tag) )
(?(DEFINE)
(?<style_tag> (?&tag) )
(?<start_tag> < (?&WS) style \b )
(?<required_attribute> type )
(?<permitted_attribute> media )
(?<standard_attribute>
dir
| lang
| title
| xml:lang
)
(?<event_attribute> (*FAIL) )
(?<permitted_attribute> (*FAIL) )
(?<deprecated_attribute> (*FAIL) )
) # end define
}six;
$strong_tag_rx = qr{
$_TAG_SUBS
(?<TAG> (?&strong_tag) )
(?(DEFINE)
(?<strong_tag> (?&tag) )
(?<start_tag>
< (?&WS)
strong
\b
)
(?<standard_attribute>
class
| dir
| ltr
| id
| lang
| style
| title
| xml:lang
)
(?<event_attribute>
on click
on dbl click
on mouse down
on mouse move
on mouse out
on mouse over
on mouse up
on key down
on key press
on key up
)
(?<required_attribute> (*FAIL) )
(?<permitted_attribute> (*FAIL) )
(?<optional_attribute> (*FAIL) )
(?<deprecated_attribute> (*FAIL) )
) # end DEFINE
}six;
$a_tag_rx = qr{
$_TAG_SUBS
(?<TAG> (?&a_tag) )
(?(DEFINE)
(?<a_tag> (?&tag) )
(?<start_tag>
< (?&WS)
a
\b
)
(?<permitted_attribute>
charset
| coords
| href
| href lang
| name
| rel
| rev
| shape
| rect
| circle
| poly
| target
)
(?<standard_attribute>
access key
| class
| dir
| ltr
| id
| lang
| style
| tab index
| title
| xml:lang
)
(?<event_attribute>
on blur
| on click
| on dbl click
| on focus
| on mouse down
| on mouse move
| on mouse out
| on mouse over
| on mouse up
| on key down
| on key press
on key up
)
(?<required_attribute> (*FAIL) )
(?<deprecated_attribute> (*FAIL) )
) # end define
}xi;
$img_tag_rx = qr{
$_TAG_SUBS
(?<TAG> (?&image_tag) )
(?(DEFINE)
(?<image_tag> (?&tag) )
(?<start_tag>
< (?&WS)
img
\b
)
(?<required_attribute>
alt
| src
)
# NB: The white space in string literals
# below DOES NOT COUNT! It just
# there for legibility.
(?<permitted_attribute>
height
| is map
| long desc
| use map
| width
)
(?<deprecated_attribute>
align
| border
| hspace
| vspace
)
(?<standard_attribute>
class
| dir
| id
| style
| title
| xml:lang
)
(?<event_attribute>
on abort
| on click
| on dbl click
| on mouse down
| on mouse out
| on key down
| on key press
| on key up
)
###########################
) # end DEFINE
}six;
}
UNITCHECK { load_patterns() }
__END__
<td class="MODULE_PRODUCTS_CELL" align="center" valign="top" height="100">
<table width="100" summary="products">
<tr>
<td align="center" height="75">
<a href="/collections.php?prod_id=50">
<img src="files/products_categories50_t.txt" border="0" alt="products" />
</a>
<br/>
</td>
</tr>
<tr>
<td align="center">
<a href="/collections.php?prod_id=50">
<strong>Buffer</strong><br />
</a>
<td>
</tr>
</table>
</td>
Эта программа при запуске производит этот вывод:
IMG tag at 304: <img src="files/products_categories50_t.txt" border="0" alt="products" />
SRC is files/products_categories50_t.txt
A tag at 214: <a href="/collections.php?prod_id=50">
HREF is /collections.php?prod_id=50
A tag at 451: <a href="/collections.php?prod_id=50">
HREF is /collections.php?prod_id=50
STRONG tag at 491: <strong>
BODY=Buffer
Выбор - ваш - или это?
Обе эти проблемы решают вашу проблему с помощью регулярных выражений. Возможно, вы сможете использовать первый из моих двух подходов. Я не могу сказать, потому что, как будто все такие вопросы заданы здесь, вы не сказали нам достаточно о данных для нас (и, возможно, и вы), чтобы точно знать, хватит ли наивного подхода.
Если это не так, у вас есть два варианта.
- Вы можете использовать более надежный и гибкий подход, предлагаемый моей второй техникой. Просто убедитесь, что вы понимаете это во всех его аспектах, потому что в противном случае вы не сможете поддерживать свой код - и никто не будет.
- Используйте класс разбора HTML.
Я считаю маловероятным, чтобы даже один человек из 1000 мог сделать первый из этих двух вариантов. В частности, я нахожу крайне неочевидным, что тот, кто просит о помощи с регулярными выражениями так же просто, как и в моем первом решении, будет человеком, способным управлять регулярными выражениями, приведенными в моем втором решении.
Что действительно оставляет вас только с одним "выбором" - если я могу использовать это слово так свободно.