Это должно работать для большинства правильно сформированных разметок, если вы не находитесь в разделе CDATA и не играли в грязные игры, переопределяя сущности:
# nasty, ugly, illegible, unmaintable — NEVER USE THIS STYLE!!!!
/<\w+(?:\s+\w+=(?:\S+|(['"])(?:(?!\1).)*?\1))*\s*\/?>/s
или более разборчиво, например
# broken out into related elements grouped by whitespace via /x
/ < \w+ (?: \s+ \w+ = (?: \S+ | (['"]) (?: (?! \1) . ) *? \1 )) * \s* \/? > /xs
и даже более разборчиво, как это:
/
# start of tag, with named ident
< \w+
# now with unlimited k=v pairs
# where k is \w+
# and v is either \S+ or else quoted
(?: \s+ \w+ = (?: \S+ # either an unquoted value,
| ( ['"] ) # or else first pick either quote
(?:
(?! \1) . # anything that isn't our quote, including brackets
) * ? # maximal should probably work here
\1 # till we see it again
)
) * # as many k=v pairs as we can find
\s * # tolerate closing whitespace
\/ ? # XHTML style close tag
> # finally done
/xs
Вы можете добавить немного помои, например, допускать пробелы в некоторых местах, где я не выше.
PHP не обязательно является лучшим языком для такой работы, хотя вы можете обойтись в крайнем случае.И самое меньшее, вы должны спрятать этот материал в функции и / или переменной где-нибудь, не оставлять его открытым как голый, учтите, что The Children Are Watching ™.
Чтобы сделать что-то более сложное, чем найти ойЯ не знаю букв или пробелов, шаблоны очень выигрывают от комментариев и пробелов.Это должно быть само собой разумеющимся, но по какой-то причине люди забывают использовать /x
для когнитивного разделения, позволяя пробелу группировать связанные вещи так же, как вы делаете с императивным кодом.
Даже если они являются декларативными программами, а не императивными,Более того, шаблоны извлекают выгоду из полной декомпозиции проблем и проектирования сверху вниз. Один из способов реализовать это - это когда у вас есть "подпрограммы регулярного выражения", которые вы объявляете отдельно от места их использования.В противном случае вы просто выполняете повторное использование кода «вырезать и вставить», то есть повторное использование кода в пессимальной сортировке.Вот пример шаблона для сопоставления тега <img>
, на этот раз с использованием реального Perl:
my $img_rx = qr{
# save capture in $+{TAG} variable
(?<TAG> (?&image_tag) )
# remainder is pure declaration
(?(DEFINE)
(?<image_tag>
(?&start_tag)
(?&might_white)
(?&attributes)
(?&might_white)
(?&end_tag)
)
(?<attributes>
(?:
(?&might_white)
(?&one_attribute)
) *
)
(?<one_attribute>
\b
(?&legal_attribute)
(?&might_white) = (?&might_white)
(?:
(?"ed_value)
| (?&unquoted_value)
)
)
(?<legal_attribute>
(?: (?&required_attribute)
| (?&optional_attribute)
| (?&standard_attribute)
| (?&event_attribute)
# for LEGAL parse only, comment out next line
| (?&illegal_attribute)
)
)
(?<illegal_attribute> \b \w+ \b )
(?<required_attribute>
alt
| src
)
(?<optional_attribute>
(?&permitted_attribute)
| (?&deprecated_attribute)
)
# NB: The white space in string literals
# below DOES NOT COUNT! It's 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
)
(?<unquoted_value>
(?&unwhite_chunk)
)
(?<quoted_value>
(?<quote> ["'] )
(?: (?! \k<quote> ) . ) *
\k<quote>
)
(?<unwhite_chunk>
(?:
# (?! [<>'"] )
(?! > )
\S
) +
)
(?<might_white> \s * )
(?<start_tag>
< (?&might_white)
img
\b
)
(?<end_tag>
(?&html_end_tag)
| (?&xhtml_end_tag)
)
(?<html_end_tag> > )
(?<xhtml_end_tag> / > )
)
}six;
Да, он становится длинным, но с увеличением длины он становится более понятным, а не меньшим. Это также более правильно. Теперь настоящая программа, в которой она используется, делает не только это, потому что вам приходится учитывать гораздо больше, чем в реальном HTML, например, CDATA, кодировках и т.д.озорные переопределения сущностей.Однако, вопреки распространенному мнению, вы можете на самом деле делать такие вещи с PHP, потому что он использует PCRE, который позволяет (?(DEFINE)...)
блоков и рекурсивных шаблонов.У меня есть более серьезные примеры такого рода вещей в моих ответах здесь , здесь , здесь , здесь и здесь.
Хорошо, хорошо, вы прочитали все это или хотя бы взглянули на них?Все еще со мной?Привет??Не забудьте дышать.Там, теперь ты будешь в порядке.:)
Конечно, есть большая серая область, где возможное уступает место невидимому, и гораздо быстрее, чем оно уступает невозможному.Если эти примеры в этих ответах, не говоря уже о них в текущем, выходят за рамки вашего текущего уровня навыков сопоставления с образцом, то вам, вероятно, следует использовать что-то еще, что часто означает, что кто-то другой сделает это за вас.