Regex: ожидаемая строка или байтоподобный объект [дубликат]

Мне нужно сопоставить все эти теги открытия:

<p>
<a href="foo">

Но не эти:

<br />
<hr class="foo" />

Я придумал это и хотел убедиться, что у меня есть Правильно. Я только фиксирую a-z.

<([a-z]+) *[^/]*?>

Я считаю, что он говорит:

  • Найти меньше, чем [, g0]
  • Найти ( и захватить) az один или несколько раз, тогда
  • Найдите ноль или более пробелов, затем
  • Найдите любой символ ноль или более раз, жадный, кроме /, затем
  • Найти большее, чем

Есть ли у меня это право? И что еще более важно, что вы думаете?

1324
задан 11 revs, 7 users 58% 26 May 2012 в 21:37
поделиться

30 ответов

Вы не можете разобрать HTML-код [X] с регулярным выражением. Поскольку HTML не может быть проанализирован с помощью регулярных выражений. Regex не является инструментом, который можно использовать для правильного анализа HTML. Поскольку я уже много раз отвечал в вопросах HTML-и-regex, использование регулярных выражений не позволит вам потреблять HTML. Регулярные выражения - это инструмент, который недостаточно совершенен для понимания конструкций, используемых HTML. HTML не является регулярным языком и, следовательно, не может быть проанализирован с помощью регулярных выражений. Запросы Regex не имеют возможности разбивать HTML на его значимые части. так много раз, но это не доходит до меня. Даже расширенные нерегулярные регулярные выражения, используемые Perl, не справляются с задачей анализа HTML. Вы никогда не заставите меня взломать. HTML - это язык достаточной сложности, который не может быть проанализирован с помощью регулярных выражений. Даже Джон Скит не может анализировать HTML, используя регулярные выражения. Каждый раз, когда вы пытаетесь проанализировать HTML с регулярными выражениями, нечестивый ребенок плачет кровью девственниц, а русские хакеры выкладывают ваш webapp. Разбор HTML с регулярным выражением вызывает тайные души в царство живых. HTML и регулярное выражение идут вместе, как любовь, брак и ритуал детоубийства. «Центр» не может удерживать слишком поздно. Сила регулярных выражений и HTML вместе в одном и том же концептуальном пространстве уничтожит ваш разум как много водянистую замазку. Если вы анализируете HTML с регулярным выражением, вы даете им и их богохульные способы, которые обрекают нас всех на бесчеловечные труды для Того, чье имя не может быть выражено на Основном многоязычном плане, он приходит. HTML-plus-regexp сжигает n erves разумного, пока вы наблюдаете, ваша психика увядает в натиске ужаса. Основанные на языке Rege̿̔̉x HTML-парсеры - это рак, который убивает StackOverflow, слишком поздно, что слишком поздно мы не можем спасти trangession of child, гарантирует, что регулярное выражение будет потреблять всю живую ткань (за исключением HTML, который он не может, как ранее пророчествовал) дорогой лорд помогите нам, как кто-либо сможет выжить в этом бедствии, используя регулярное выражение для анализа HTML, обрек человечество на вечность страшных пыток и дыр в безопасности, используя регулярное выражение в качестве инструмента для обработки HTML, устанавливает нарушение между этим миром и областью страха сущностных сущностей (например, SGML-сущностей , но более коррумпированный), простое представление о мире reg ex parsers для HTML будет вставлять , тантьё переносить сознание программиста в мир непрестанного крика, он приходит, зловонная слизистая регулярная инфекция wil l пожирайте ваш парсер, приложение и существование в HT ML на все время, например Visual Basic, только хуже, он приходит, не делает h e com̡e̶s, ̕h̵i s неудовлетворительное радианское разрушение все улучшения, HTML-теги lea͠ki̧n͘g fr̶ǫm ̡yo ͟ur eye͢s̸ ̛l̕ik͏e liq uid pain, песня reggular exp ression parsing будет распространять голоса mor tal man из sp здесь я вижу, что вы можете видеть, что это красиво. f inal snuf пальцы лжи s человека ALL IS LOŚ͖̩͇̗̪̏̈T A LL I SL OST pon̷y он приходит, он c̶̮omes он co mes the ich или пронизывает весь МОЙ ЛИЦ МОЙ ЛИЦО ᵒh god n o NO NOO̼ O ON Θ остановить a * ̶͑̾̾ ̅ͫ͏̙̤g͇̫͛͆̾ͫ̑͆l͖͉̗̩̳̟̍ͫͥͨe̠̅s ͎a̧͈͖r̽̾̈́͒͑e n ot rè̑ͧ̌aͨl̘̝̙ͤ̾̆ ZA̡͊͠͝LGΌ ISͮ҉̯͈͕̹̘ T O͇̹̺Ɲ̴ȳ̳ TH̘ Ë͖̉ ͠P̯͍̭O̚ N̐Y̡ H̸̡̪̯ͨ͊̽̅̾Ȩ̬̩̾͛ͪ̈͘ ̶̧̨̹̭̯ͧ̾ͬC̷̙̝͖ͭ̏ͥͮ͟Oͮ͏̮̪̝͍M̖͊̒ͪͩͬ̚̚͜Ȇ̴̟̟͙̞ͩ͌͝ S̨̥̫͎̭ͯ̿̔

< hr>

Вы пробовали использовать синтаксический анализатор XML в stead?


Замечание модератора

Это сообщение заблокировано, чтобы предотвратить нежелательные изменения его содержимого. Сообщение выглядит так, как должно выглядеть - проблем с его содержанием нет. Пожалуйста, не помещайте это для нашего внимания.

4422
ответ дан 7 revs, 5 users 36% 26 August 2018 в 13:07
поделиться

Есть люди, которые скажут вам, что Земля круглая (или, возможно, Земля - ​​сплющенный сфероид, если они хотят использовать странные слова). Они лгут.

Есть люди, которые скажут вам, что регулярные выражения не должны быть рекурсивными. Они ограничивают вас. Они должны подчинить вас, и они делают это, удерживая вас в невежестве.

Вы можете жить в своей реальности или принимать красную таблетку.

Как лорд Маршал (он родственник из класса Marshal .NET?), я видел Underverse Stack Based Regex-Verse и возвращался с помощью знаний о силе, которые вы не можете себе представить. Да, я думаю, что один из них защищал их, но они смотрели футбол по телевизору, поэтому это было не сложно.

Я думаю, что XML-пример довольно прост. RegEx (в синтаксисе .NET), сдутый и закодированный в base64, чтобы облегчить понимание вашим слабым умом, должен быть примерно таким:

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
+r/vD34mUADO1P4/AQAA//8=

Параметры для установки: RegexOptions.ExplicitCapture , Группа захвата, которую вы ищете, - ELEMENTNAME. Если группа захвата ERROR не пуста, тогда произошла ошибка синтаксического анализа, и регекс остановился.

Если у вас есть проблемы с переустановкой его на понятное для пользователя регулярное выражение, это должно помочь:

static string FromBase64(string str)
{
    byte[] byteArray = Convert.FromBase64String(str);

    using (var msIn = new MemoryStream(byteArray))
    using (var msOut = new MemoryStream()) {
        using (var ds = new DeflateStream(msIn, CompressionMode.Decompress)) {
            ds.CopyTo(msOut);
        }

        return Encoding.UTF8.GetString(msOut.ToArray());
    }
}

Если вы не уверены, нет, я НЕ шучу (но, возможно, я лгу). Это будет работать. Я собрал тонны тестов для тестирования, и я даже использовал (часть) тесты соответствия . Это токенизатор, а не полноразмерный парсер, поэтому он будет разделять только XML на его компонентные маркеры. Он не будет анализировать / интегрировать DTD.

Ох ... если вы хотите исходный код регулярного выражения с некоторыми вспомогательными методами:

regex tokenize xml или полное регулярное выражение

455
ответ дан 11 revs, 9 users 71% 26 August 2018 в 13:07
поделиться
<?php
$selfClosing = explode(',', 'area,base,basefont,br,col,frame,hr,img,input,isindex,link,meta,param,embed');

$html = '
<p><a href="#">foo</a></p>
<hr/>
<br/>
<div>name</div>';

$dom = new DOMDocument();
$dom->loadHTML($html);
$els = $dom->getElementsByTagName('*');
foreach ( $els as $el ) {
    $nodeName = strtolower($el->nodeName);
    if ( !in_array( $nodeName, $selfClosing ) ) {
        var_dump( $nodeName );
    }
}

Выход:

string(4) "html"
string(4) "body"
string(1) "p"
string(1) "a"
string(3) "div"

В основном просто определяют имена узлов узлов, которые закрываются самостоятельно, загружают всю строку html в библиотеку DOM, захватывают все элементы, перебирают и отфильтровывают которые не закрываются и не работают на них.

Я уверен, что вы уже знаете, что вам не следует использовать регулярное выражение для этой цели.

154
ответ дан 2 revs 26 August 2018 в 13:07
поделиться

Всякий раз, когда мне нужно быстро извлечь что-то из HTML-документа, я использую Tidy, чтобы преобразовать его в XML, а затем использовать XPath или XSLT, чтобы получить то, что мне нужно. В вашем случае что-то вроде этого:

//p/a[@href='foo']
90
ответ дан 2 revs, 2 users 67% 26 August 2018 в 13:07
поделиться

Вы хотите, чтобы первый >, которому не предшествовал /. Посмотрите здесь , чтобы узнать, как это сделать.

Однако наивная реализация этого приведет к сопоставлению <bar/></foo> в этом примере документа

<foo><bar/></foo>

Можете ли вы предоставить немного больше информации о проблема, которую вы пытаетесь решить? Вы выполняете итерацию через теги программно?

133
ответ дан 2 revs, 2 users 89% 26 August 2018 в 13:07
поделиться

W3C объясняет разбор в форме псевдорежима: W3C Link

Следуйте за ссылками на QName, S и Attribute, чтобы получить более четкое картина. Исходя из этого, вы можете создать довольно хорошее регулярное выражение для обработки таких вещей, как снятие тегов.

122
ответ дан 2 revs, 2 users 92% 26 August 2018 в 13:07
поделиться

Сунь Цзы, древний китайский стратег, генерал и философ, сказал:

Говорят, что если вы знаете своих врагов и знаете себя, вы можете выиграть сто сражений без единого потеря. Если вы знаете только себя, но не своего оппонента, вы можете победить или проиграть. Если вы не знаете ни себя, ни своего врага, вы всегда будете подвергать себя опасности.

В этом случае ваш враг - это HTML, и вы либо сами, либо регулярное выражение. Возможно, вы даже Perl с нерегулярным регулярным выражением. Знайте HTML. Знайте сами.

Я написал хайку, описывающий характер HTML.

HTML has
complexity exceeding
regular language.

Я также написал хайку, описывающий характер регулярного выражения в Perl.

The regex you seek
is defined within the phrase
<([a-zA-Z]+)(?:[^>]*[^/]*)?>
165
ответ дан 2 revs, 2 users 98% 26 August 2018 в 13:07
поделиться

Попробуйте:

<([^\s]+)(\s[^>]*?)?(?<!/)>

Он похож на ваш, но последний > не должен быть после косой черты, а также принимает h1.

177
ответ дан 3 revs, 2 users 77% 26 August 2018 в 13:07
поделиться

Недавно я написал HTML-дезинфицирующее средство в Java. Он основан на смешанном подходе регулярных выражений и Java-коде. Лично я ненавижу регулярные выражения и его глупость (читаемость, ремонтопригодность и т. Д.), Но если вы уменьшите объем своих приложений, это может соответствовать вашим потребностям. Во всяком случае, мой дезинфицирующее средство использует белый список для тегов HTML и черный список для некоторых атрибутов стиля.

Для вашего удобства я создал игровое поле, чтобы вы могли проверить, соответствует ли код вашим требованиям: игровая площадка и код Java . Ваши отзывы будут оценены.

Существует небольшая статья, описывающая эту работу в моем блоге: http://roberto.open-lab.com

55
ответ дан 3 revs, 3 users 64%Roberto 26 August 2018 в 13:07
поделиться

Что касается методов RegExp для синтаксического анализа (x) HTML, то ответ всем тем, кто говорил о некоторых ограничениях, заключается в следующем: вы недостаточно подготовлены, чтобы управлять силой этого мощного оружия, поскольку NOBODI здесь говорил о рекурсии.

Сотрудник RegExp-agnostic уведомил меня об этом обсуждении, которое, конечно же, не является первым в Интернете по этой старой и горячей теме.

После прочтения некоторых сообщений первый вещь, которую я сделал, искала строку «? R» в этой теме. Второй - искать «рекурсию». Нет, святая корова, не найдено. Поскольку никто не упоминал о главном механизме, на котором построен парсер, я скоро понял, что никто не понял.

Если парсер (x) HTML нуждается в рекурсии, парсер RegExp без рекурсии недостаточно для этой цели , Это простая конструкция.

Черное искусство RegExp сложно освоить, поэтому, возможно, есть еще возможности, которые мы оставили во время тестирования и тестирования нашего личного решения, чтобы захватить всю сеть в одной руке ... Ну , Я уверен в этом:)

Вот волшебный паттерн:

$pattern = "/<([\w]+)([^>]*?)(([\s]*\/>)|(>((([^<]*?|<\!\-\-.*?\-\->)|(?R))*)<\/\\1[\s]*>))/s";

Просто попробуйте. Он написан как строка PHP, поэтому модификатор «s» делает классы include новыми. Вот пример заметки в руководстве по PHP, которое я написал в январе: Ссылка

(Позаботьтесь, в этой заметке я ошибочно использовал модификатор «m», его следует стереть, несмотря на он отбрасывается движком RegExp, поскольку не использовалось no ^ или $ anchorage.

Теперь мы можем говорить о границах этого метода с более информированной точки зрения:

  1. в соответствии с конкретной реализацией движка RegExp, рекурсия может иметь ограничение в количестве проанализированных вложенных шаблонов, но это зависит от используемого языка
  2. , хотя поврежденный (x) HTML не управляет

Во всяком случае, это только шаблон RegExp, но он раскрывает возможность разработки множества мощных реализаций. Я написал этот шаблон, чтобы заставить рекурсивный парсер спуска механизма шаблона, который я построил в своей структуре, и производительность действительно велика, как во время выполнения, так и в использовании памяти (ничего общего с другими механизмами шаблонов, которые используйте тот же синтаксис).

66
ответ дан 3 revs, 3 users 75% 26 August 2018 в 13:07
поделиться

Если вам это нужно для PHP:

Функции PHP DOM не будут работать должным образом, если не будут правильно отформатированы XML. Независимо от того, насколько лучше их использование для остальной части человечества.

simplehtmldom хорош, но я нашел его немного ошибкой, и он довольно тяжелый для памяти [Will crash на больших страницах.]

Я никогда не использовал querypath , поэтому не могу прокомментировать его полезность.

Еще один пример - мой DOMParser , который очень светлый для ресурсов, и я долгое время использовал его. Простота обучения & amp;

Для Python и Java были опубликованы похожие ссылки.

Для downvoters - я написал свой класс только тогда, когда синтаксические анализаторы XML оказались не в состоянии противостоять реальному использованию. Религиозное downvoting просто препятствует тому, чтобы полезные ответы были отправлены - держите вещи в пределах перспективы вопроса, пожалуйста.

105
ответ дан 4 revs, 2 users 98% 26 August 2018 в 13:07
поделиться

Я предлагаю использовать QueryPath для синтаксического разбора XML и HTML в PHP. В основном это тот же синтаксис, что и jQuery, только на стороне сервера.

255
ответ дан 4 revs, 4 users 57% 26 August 2018 в 13:07
поделиться

Есть несколько хороших регулярных выражений для замены HTML с помощью BBCode здесь . Обратите внимание на то, что он не пытается полностью разобрать HTML, просто для того, чтобы его дезинфицировать. Вероятно, он может убить теги, которые его простой «парсер» не может понять.

Например:

$store =~ s/http:/http:\/\//gi;
$store =~ s/https:/https:\/\//gi;
$baseurl = $store;

if (!$query->param("ascii")) {
    $html =~ s/\s\s+/\n/gi;
    $html =~ s/<pre(.*?)>(.*?)<\/pre>/\[code]$2\[\/code]/sgmi;
}

$html =~ s/\n//gi;
$html =~ s/\r\r//gi;
$html =~ s/$baseurl//gi;
$html =~ s/<h[1-7](.*?)>(.*?)<\/h[1-7]>/\n\[b]$2\[\/b]\n/sgmi;
$html =~ s/<p>/\n\n/gi;
$html =~ s/<br(.*?)>/\n/gi;
$html =~ s/<textarea(.*?)>(.*?)<\/textarea>/\[code]$2\[\/code]/sgmi;
$html =~ s/<b>(.*?)<\/b>/\[b]$1\[\/b]/gi;
$html =~ s/<i>(.*?)<\/i>/\[i]$1\[\/i]/gi;
$html =~ s/<u>(.*?)<\/u>/\[u]$1\[\/u]/gi;
$html =~ s/<em>(.*?)<\/em>/\[i]$1\[\/i]/gi;
$html =~ s/<strong>(.*?)<\/strong>/\[b]$1\[\/b]/gi;
$html =~ s/<cite>(.*?)<\/cite>/\[i]$1\[\/i]/gi;
$html =~ s/<font color="(.*?)">(.*?)<\/font>/\[color=$1]$2\[\/color]/sgmi;
$html =~ s/<font color=(.*?)>(.*?)<\/font>/\[color=$1]$2\[\/color]/sgmi;
$html =~ s/<link(.*?)>//gi;
$html =~ s/<li(.*?)>(.*?)<\/li>/\[\*]$2/gi;
$html =~ s/<ul(.*?)>/\[list]/gi;
$html =~ s/<\/ul>/\[\/list]/gi;
$html =~ s/<div>/\n/gi;
$html =~ s/<\/div>/\n/gi;
$html =~ s/<td(.*?)>/ /gi;
$html =~ s/<tr(.*?)>/\n/gi;

$html =~ s/<img(.*?)src="(.*?)"(.*?)>/\[img]$baseurl\/$2\[\/img]/gi;
$html =~ s/<a(.*?)href="(.*?)"(.*?)>(.*?)<\/a>/\[url=$baseurl\/$2]$4\[\/url]/gi;
$html =~ s/\[url=$baseurl\/http:\/\/(.*?)](.*?)\[\/url]/\[url=http:\/\/$1]$2\[\/url]/gi;
$html =~ s/\[img]$baseurl\/http:\/\/(.*?)\[\/img]/\[img]http:\/\/$1\[\/img]/gi;

$html =~ s/<head>(.*?)<\/head>//sgmi;
$html =~ s/<object>(.*?)<\/object>//sgmi;
$html =~ s/<script(.*?)>(.*?)<\/script>//sgmi;
$html =~ s/<style(.*?)>(.*?)<\/style>//sgmi;
$html =~ s/<title>(.*?)<\/title>//sgmi;
$html =~ s/<!--(.*?)-->/\n/sgmi;

$html =~ s/\/\//\//gi;
$html =~ s/http:\//http:\/\//gi;
$html =~ s/https:\//https:\/\//gi;

$html =~ s/<(?:[^>'"]*|(['"]).*?\1)*>//gsi;
$html =~ s/\r\r//gi;
$html =~ s/\[img]\//\[img]/gi;
$html =~ s/\[url=\//\[url=/gi;
69
ответ дан 4 revs, 4 users 88% 26 August 2018 в 13:07
поделиться

Отказ от ответственности: используйте парсер, если у вас есть опция. Тем не менее ...

Это регулярное выражение, которое я использую (!) Для соответствия тэгам HTML:

<(?:"[^"]*"['"]*|'[^']*'['"]*|[^'">])+>

Это может быть не идеально, но я запустил этот код через lot HTML. Обратите внимание, что он даже ловит странные вещи, такие как <a name="badgenerator"">, которые появляются в Интернете.

Думаю, чтобы он не соответствовал самодостаточным тегам, вы либо захотите использовать Kobi :

<(?:"[^"]*"['"]*|'[^']*'['"]*|[^'">])+(?<!/\s*)>

или просто объединить, если и если нет.

To downvoters: Это рабочий код из реального продукта. Я сомневаюсь, что кто-либо читает эту страницу, создается впечатление, что социально приемлемо использовать регулярные выражения для HTML.

Предостережение. Я должен заметить, что это регулярное выражение все еще ломается при наличии блоков CD87, комментариев и элементов сценария и стиля. Хорошая новость заключается в том, что вы можете избавиться от тех, кто использует регулярное выражение ...

1020
ответ дан 5 revs, 2 users 92% 26 August 2018 в 13:07
поделиться

Мне нравится анализировать HTML с регулярными выражениями. Я не пытаюсь разбирать идиот HTML, который намеренно нарушен. Этот код является моим основным парсером (версия Perl):

$_ = join "",<STDIN>; tr/\n\r \t/ /s; s/</\n</g; s/>/>\n/g; s/\n ?\n/\n/g;
s/^ ?\n//s; s/ $//s; print

Он называется htmlsplit, разбивает HTML на строки, с одним тегом или фрагментом текста в каждой строке. Затем линии могут быть обработаны другими текстовыми инструментами и сценариями, такими как grep , sed , Perl и т. Д. Я даже не шучу :) Наслаждайтесь.

Достаточно просто переписать мой скрипт Perl-all-first Perl в приятную поточную вещь, если вы хотите обрабатывать огромные веб-страницы. Но это действительно не обязательно.

Бьюсь об заклад, я заберусь для этого.

HTML Split


Против моего ожидая, что это получило некоторые upvotes, поэтому я предлагаю несколько правильных выражений:

/(<.*?>|[^<]+)\s*/g    # get tags and text
/(\w+)="(.*?)"/g       # get attibutes

Они хороши для XML / XHTML.

С небольшими вариациями он может справиться с беспорядочным HTML ... или сначала конвертировать HTML -> XHTML.


Лучший способ записи регулярных выражений - в Lex / Yacc стиль, а не непрозрачные однострочные или прокомментированные многострочные чудовища. Я не делал этого здесь; эти им едва ли нужны.

84
ответ дан 5 revs, 3 users 69% 26 August 2018 в 13:07
поделиться
<\s*(\w+)[^/>]*>

Объясненные детали:

<: начальный символ

\s*: он может иметь пробелы перед именем тега (уродливым, но возможным).

(\w+): теги могут содержать буквы и цифры (h1). Ну, \w также соответствует «_», но это не мешает, я думаю. Если любопытное использование ([a-zA-Z0-9] +).

[^/>]*: все, кроме > и /, до закрытия >

>: закрытие >

UNRELATED

И для парней, которые недооценивают регулярные выражения, говоря, что они только настолько сильны, как обычные языки:

anbanban, который не является регулярный и даже контекстно-свободный, можно сопоставить с ^(a+)b\1b\1$

Обратное обращение FTW !

59
ответ дан 5 revs, 4 users 73% 26 August 2018 в 13:07
поделиться

Если вы просто пытаетесь найти эти теги (без амбиций синтаксического анализа), попробуйте это регулярное выражение:

/<[^/]*?>/g

Я написал его через 30 секунд и протестировал здесь: http: //gskinner.com/RegExr/

Он соответствует типам тегов, о которых вы упомянули, игнорируя типы, которые вы сказали игнорировать.

84
ответ дан 6 revs, 2 users 96% 26 August 2018 в 13:07
поделиться

Хотя верно, что запрос регулярных выражений для синтаксического анализа произвольного HTML похож на прошение начинающему писать операционную систему, иногда бывает целесообразно проанализировать ограниченный , известный набор HTML.

Если у вас есть небольшой набор HTML-страниц, которые вы хотите очистить данные, а затем вложить в базу данных, регулярные выражения могут работать нормально. Например, недавно я хотел получить имена, партии и округа австралийских федеральных представителей, которые я сошел с веб-сайта парламента. Это была ограниченная одноразовая работа.

Regexes отлично справились со мной и были очень быстрыми, чтобы настроить.

2931
ответ дан 8 revs, 8 users 40% 26 August 2018 в 13:07
поделиться

Не слушайте этих парней. Вы действительно можете анализировать контекстно-свободные грамматики с регулярным выражением, если вы разбиваете задачу на более мелкие части. Вы можете сгенерировать правильный шаблон с помощью скрипта, который выполняет каждый из этих действий, чтобы:

  1. Решить проблему остановки.
  2. Построить круг (имитировать «линейку и компас» метод для этого).
  3. Разработайте проблему с продавцом в O (log n).
  4. Шаблон будет довольно большим, поэтому убедитесь, что у вас есть алгоритм, который без потерь сжимает случайные данные.
  5. Почти там - просто разделите все это к нулю. Easy-peasy.

Я еще не выяснил последнюю часть, но я знаю, что приближаюсь. Мой код продолжает бросать CthulhuRlyehWgahnaglFhtagnException в последнее время, поэтому я собираюсь передать его на VB 6 и использовать On Error Resume Next. Я обновлю код, как только я исследую эту странную дверь, которая только что открылась в стене. Хмм.

P.S. Пьер де Ферма также выяснил, как это сделать, но край, который он писал, был недостаточно большим для кода.

1173
ответ дан 9 revs 26 August 2018 в 13:07
поделиться

В оболочке вы можете анализировать HTML , используя:


Связанный (почему вы не должны использовать регулярное выражение):

285
ответ дан 9 revs, 5 users 65% 26 August 2018 в 13:07
поделиться

Как уже отмечалось многими, HTML не является обычным языком, который может затруднить его синтаксический анализ. Мое решение состоит в том, чтобы превратить его в обычный язык, используя аккуратную программу, а затем использовать синтаксический анализатор XML для использования результатов. Для этого есть много хороших вариантов. Моя программа написана с использованием Java с библиотекой jtidy , чтобы превратить HTML в XML, а затем Jaxen в xpath в результат.

61
ответ дан Corey Sanders 26 August 2018 в 13:07
поделиться

Хотя это не подходит и эффективно использовать регулярные выражения для этой цели, иногда регулярные выражения предоставляют быстрые решения для простых проблем совпадения, и, на мой взгляд, не так уж и сложно использовать регулярные выражения для тривиальных работ.

Существует окончательное сообщение в блоге о совпадении сокровенных HTML-элементов, написанных Стивеном Левитаном.

48
ответ дан Emre Yazici 26 August 2018 в 13:07
поделиться

Я не знаю вашей конкретной потребности в этом, но если вы также используете .NET, не могли бы вы использовать Html Agility Pack ?

Выдержка:

Это библиотека .NET-кода, которая позволяет анализировать HTML-файлы вне Интернета. Синтаксический анализатор очень толерантен с искаженным HTML «реальным миром».

149
ответ дан GONeale 26 August 2018 в 13:07
поделиться

Вот парсер на основе PHP , который анализирует HTML с использованием некоторого нечестивого регулярного выражения. Как автор этого проекта, я могу сказать вам, что можно анализировать HTML с регулярным выражением, но не эффективно. Если вам нужно решение на стороне сервера (как и для моего плагина wp-Typography WordPress ), это работает.

73
ответ дан kingjeffrey 26 August 2018 в 13:07
поделиться

Я согласен, что правильный инструмент для синтаксического анализа XML и , особенно HTML , является синтаксическим анализатором, а не механизмом регулярных выражений. Однако, как указывали другие, иногда использование регулярного выражения выполняется быстрее, проще и выполняется, если вы знаете формат данных.

Microsoft фактически имеет раздел Рекомендации по регулярным выражениям в .NET Framework и, в частности, говорит о . Рассмотрим [вход] источника входного сигнала .

Регулярные выражения имеют ограничения, но вы считали следующее?

.NET framework уникален, когда речь заходит о регулярных выражениях в том, что он поддерживает Определения балансировочной группы .

По этой причине я считаю, что вы можете анализировать XML с помощью регулярных выражений. Обратите внимание, однако, что он должен быть достоверным. XML ( браузеры очень прощают HTML и допускают плохой синтаксис XML внутри HTML ). Это возможно, так как «Определение балансировки группы» позволит механизму регулярных выражений действовать как КПК.

Цитата из статьи 1, процитированной выше:

.NET Regular Expression Двигатель

Как описано выше, правильно сбалансированные конструкции не могут быть описаны регулярным выражением. Тем не менее, механизм регулярного выражения .NET предоставляет несколько конструкций, которые позволяют распознавать сбалансированные конструкции.

  • (?<group>) - выталкивает захваченный результат в стек захвата с помощью группы имен.
  • (?<-group>) - отображает верхний захват с группой имен с захвата stack.
  • (?(group)yes|no) - соответствует дате, если существует группа с группой имен, в противном случае не соответствует какой-либо детали.

Эти конструкции допускают регулярную .NET выражение для подражания ограниченному КПК, по существу позволяя простые версии операций стека: push, pop и empty. Простые операции в значительной степени эквивалентны приращению, уменьшению и сравнению с нулем соответственно. Это позволяет механизму регулярного выражения .NET распознавать подмножество контекстно-свободных языков, в частности тех, которые требуют простого счетчика. Это, в свою очередь, позволяет нетрадиционным регулярным выражениям .NET распознавать индивидуально правильно сбалансированные конструкции.

Рассмотрим следующее регулярное выражение:

(?=<ul\s+id="matchMe"\s+type="square"\s*>)
(?>
   <!-- .*? -->                  |
   <[^>]*/>                      |
   (?<opentag><(?!/)[^>]*[^/]>)  |
   (?<-opentag></[^>]*[^/]>)     |
   [^<>]*
)*
(?(opentag)(?!))

Использовать флаги :

  • Singleline
  • IgnorePatternWhitespace (необязательно, если вы сбрасываете регулярное выражение и удаляете все пробелы)
  • IgnoreCase (необязательно)

Объяснение регулярного выражения (inline)

(?=<ul\s+id="matchMe"\s+type="square"\s*>) # match start with <ul id="matchMe"...
(?>                                        # atomic group / don't backtrack (faster)
   <!-- .*? -->                 |          # match xml / html comment
   <[^>]*/>                     |          # self closing tag
   (?<opentag><(?!/)[^>]*[^/]>) |          # push opening xml tag
   (?<-opentag></[^>]*[^/]>)    |          # pop closing xml tag
   [^<>]*                                  # something between tags
)*                                         # match as many xml tags as possible
(?(opentag)(?!))                           # ensure no 'opentag' groups are on stack

Вы можете попробовать это на A Better .NET Regular Expression Tester .

Я использовал источник выборки:

<html>
<body>
<div>
   <br />
   <ul id="matchMe" type="square">
      <li>stuff...</li>
      <li>more stuff</li>
      <li>
          <div>
               <span>still more</span>
               <ul>
                    <li>Another &gt;ul&lt;, oh my!</li>
                    <li>...</li>
               </ul>
          </div>
      </li>
   </ul>
</div>
</body>
</html>

Это нашло совпадение:

   <ul id="matchMe" type="square">
      <li>stuff...</li>
      <li>more stuff</li>
      <li>
          <div>
               <span>still more</span>
               <ul>
                    <li>Another &gt;ul&lt;, oh my!</li>
                    <li>...</li>
               </ul>
          </div>
      </li>
   </ul>

, хотя оно получилось так:

<ul id="matchMe" type="square">           <li>stuff...</li>           <li>more stuff</li>           <li>               <div>                    <span>still more</span>                    <ul>                         <li>Another &gt;ul&lt;, oh my!</li>                         <li>...</li>                    </ul>               </div>           </li>        </ul>

Наконец, Мне очень понравилась статья Джеффа Этвуда: Parsing Html Путь Ктулху . Забавно, он цитирует ответ на этот вопрос, который в настоящее время имеет более 4 кв голосов.

261
ответ дан Macro Man 26 August 2018 в 13:07
поделиться

Мне кажется, вы пытаетесь сопоставить теги без «/» в конце. Попробуйте следующее:

<([a-zA-Z][a-zA-Z0-9]*)[^>]*(?<!/)>
52
ответ дан manixrock 26 August 2018 в 13:07
поделиться

Хотя ответы, которые вы не можете проанализировать HTML с регулярными выражениями, верны, они не применяются здесь. OP просто хочет проанализировать один тег HTML с регулярными выражениями, и это то, что можно сделать с помощью регулярного выражения.

Предлагаемое регулярное выражение неверно:

<([a-z]+) *[^/]*?>

Если вы добавите что-то в регулярное выражение, путем обратного отслеживания его можно заставить сопоставить такие глупые вещи, как <a >>, [^/] слишком разрешительно. Также обратите внимание, что <space>*[^/]* является избыточным, поскольку [^/]* также может соответствовать пробелам.

Мое предложение было бы

<([a-z]+)[^>]*(?<!/)>

Где (?<! ... ) (в Perl-регулярных выражениях) отрицательный внешний вид. Он читает «a», затем слово, а затем все, что не является>, последнее из которых не может быть /, а затем> «.

Обратите внимание, что это позволяет такие вещи, как <a/ > ( как и исходное регулярное выражение), поэтому, если вы хотите что-то более ограничительное, вам нужно создать регулярное выражение для соответствия парам атрибутов, разделенных пробелами.

213
ответ дан moritz 26 August 2018 в 13:07
поделиться

Раньше я использовал инструмент с открытым исходным кодом, названный HTMLParser . Он разработан, чтобы анализировать HTML по-разному и хорошо служит цели. Он может анализировать HTML как другой treenode, и вы можете легко использовать его API для получения атрибутов из узла. Проверьте это и посмотрите, поможет ли это вам.

90
ответ дан wen 26 August 2018 в 13:07
поделиться

Вот решение:

<?php
// here's the pattern:
$pattern = '/<(\w+)(\s+(\w+)\s*\=\s*(\'|")(.*?)\\4\s*)*\s*(\/>|>)/';

// a string to parse:
$string = 'Hello, try clicking <a href="#paragraph">here</a>
    <br/>and check out.<hr />
    <h2>title</h2>
    <a name ="paragraph" rel= "I\'m an anchor"></a>
    Fine, <span title=\'highlight the "punch"\'>thanks<span>.
    <div class = "clear"></div>
    <br>';

// let's get the occurrences:
preg_match_all($pattern, $string, $matches, PREG_PATTERN_ORDER);

// print the result:
print_r($matches[0]);
?>

Чтобы проверить его глубоко, я ввел в теги автоматического закрытия строки, например:

  1. & lt; hr / & gt;
  2. & lt; br / & gt;
  3. & lt; br & gt;

Я также вводил теги с:

  1. один атрибут
  2. содержит более одного атрибута
  3. , значение которого привязано либо в одинарные кавычки, либо в двойные кавычки
  4. атрибуты, содержащие одинарные кавычки, когда разделитель является двойным цитата и наоборот
  5. «нечеткие» атрибуты с пробелом перед символом «=» после него и до и после него.

Если вы найдете что-то, что не работает в доказательстве концепции выше, я доступен для анализа кода, чтобы улучшить свои навыки.

& lt; EDIT & gt; Я забыл, что вопрос от пользователя заключался в том, чтобы избежать разбора самозакрывающихся тегов. В этом случае шаблон проще, превратившись в это:

$pattern = '/<(\w+)(\s+(\w+)\s*\=\s*(\'|")(.*?)\\4\s*)*\s*>/';

Пользователь @ridgerunner заметил, что шаблон не позволяет без кавычек атрибутов или атрибутов без значения. В этом случае тонкая настройка приводит к следующему шаблону:

$pattern = '/<(\w+)(\s+(\w+)(\s*\=\s*(\'|"|)(.*?)\\5\s*)?)*\s*>/';

& lt; / EDIT & gt;

Понимание шаблона

Если кто-то заинтересован в обучении подробнее о шаблоне, я предоставляю некоторую строку:

  1. первое подвыражение (\ w +) соответствует имени тега
  2. , второе подвыражение содержит шаблон атрибут. Он состоит из: одного или нескольких пробелов \ s + имя атрибута (\ w +) ноль или более пробелов \ s * (возможно или нет, оставляя здесь пробелы) символ "=" снова, ноль или более пробелов разделитель значения атрибута, одинарная или двойная кавычка («|»). В шаблоне одиночная кавычка экранируется, потому что она совпадает с разделителем строки PHP. Это подвыражение захватывается скобками, поэтому на него можно ссылаться снова для синтаксического анализа закрытия атрибута, поэтому очень важно значение атрибута, сопоставляемое почти : (. *?); в этом конкретном синтаксисе, используя жадное соответствие ( вопросительный знак после звездочки), механизм RegExp позволяет использовать оператор «look-ahead», который соответствует чему-либо, но что следует за этим подвыражением, здесь весело: элемент \ 4 является оператором обратной ссылки, который ссылается на подзадачу, выражение, определенное ранее в шаблоне, в данном случае я имею в виду четвертое подвыражение, которое является первым a ttribute delimiter обнаружен ноль или более пробелов \ s * конец суб-выражения атрибута заканчивается здесь, с указанием нуля или более возможных вхождений, заданных звездочкой.
  3. Затем, поскольку тег может заканчиваться пробелом перед «& gt;», символ, ноль или более пробелов сопоставляются с подшаблоном \ s *.
  4. Тег, который должен соответствовать, может заканчиваться простым «& gt;» символ или возможное закрытие XHTML, которое использует перед ним косую черту: (/> |>). Слэш, конечно, сбежал, поскольку он совпадает с разделителем регулярных выражений.

Небольшой совет: чтобы лучше проанализировать этот код, необходимо посмотреть исходный код, сгенерированный с тех пор, как я не представил любые специальные символы HTML.

84
ответ дан 6 revs, 2 users 96% 26 August 2018 в 13:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: