Функция match () Javascript, возвращающая полностью соответствующий тег - PullRequest
2 голосов
/ 05 июня 2011
console.log( html.match( /<a href="(.*?)">[^<]+<\/a>/g ));

Вместо того, чтобы возвращать только URL, как:

http://google, http://yahoo.com

Возвращается весь тег:

<a href="http://google.com">Google.com</a>, <a href="http://yahoo.com">Yahoo.com</a>

Почему это так?

Ответы [ 2 ]

3 голосов
/ 10 июня 2011

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

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

Из четырех проблем, перечисленных предыдущим респондентом:

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

Только номер 3 создает значительные проблемы для решения single с регулярными выражениями, но также оказывается совершенно нестандартным HTML, который никогда не должен появляться в документе HTML.(Обратите внимание, что если вы найдете HTML, содержащий свойства тегов без разделителей, есть регулярное выражение, которое будет соответствовать им, но я утверждаю, что их не стоит извлекать. YMMV - Ваш пробег может отличаться.)

ИзвлечьДля привязки ссылок (hrefs) с использованием регулярных выражений из HTML вы должны использовать это регулярное выражение (в закомментированной форме):

<          # a literal '<'
a          # a literal 'a'
[^>]+?     # one or more chars which are not '>' (non-greedy)
href=      # literal 'href='
('|")      # either a single or double-quote captured into group #1
([^\1]+?)  # one or more chars that are not the group #1, captured into group #2
\1         # whatever capture group #1 matched

, которое без комментариев:

<a[^>]+?href=('|")([^\1]+?)\1

(Примечаниечто нам не нужно ничего совпадать с последним конечным разделителем, включая остальную часть тега, так как все, что нас интересует, - это якорная ссылка.)

В JavaScript и в предположении, что «источник» содержит HTML-код, из которогоВы хотите извлечь якорные ссылки:

var source='<a href="double-quote test">\n'+
           '<a href=\'single-quote test\'>\n'+
           '<a class="foo" href="leading prop test">\n'+
           '<a    href="trailing prop test"   class="foo">\n'+
           '<a style="bar" link="baz" '+
                'name="quux" '+
                'href="multiple prop test" class="foo">\n'+
           '<a class="foo"\n href="inline newline test"\n style="bar"\n />';

, которые при выводе на консоль читаются как:

<a href="double-quote test">
<a href='single-quote test'>
<a class="foo" href="leading prop test">
<a    href="trailing prop test"   class="foo">
<a style="bar" link="baz" name="quux" href="multiple prop test" class="foo">
<a class="foo" 
 href="inline newline test"
 style="bar"
 />

, вы должны написать следующее:

var RE=new RegExp(/<a[^>]+?href=('|")([^\1]+?)\1/gi),
    match;

while(match=RE.exec(source)) {
    console.log(match[2]);
}

который выводит на консоль следующие строки:

double-quote test
single-quote test
leading prop test
trailing prop test
multiple prop test
inline newline test

Примечания:

  1. Код, протестированный в nodejs v0.5.0-pre, но должен работать под любым современным JavaScript.

  2. Поскольку регулярное выражение использует группу захвата № 1, чтобы отметить начальную кавычку с разделителями, результирующая ссылка появляется в группе захвата № 2.

  3. Возможно, вы захотите проверить существование, тип и длинусовпадения с использованием:

    
    if(match && typeof match === 'object' && match.length > 1) {
        console.log(match[2]);
    }
    
    , но это действительно не должно быть необходимо, так как RegExp.exec () возвращает 'null' при ошибке.Также обратите внимание, что правильным типом соответствия является «объект», а не «массив».
3 голосов
/ 05 июня 2011

Требуется RegExp#exec и цикл, обращающийся к элементу по индексу 1 результата совпадения, а не String.match.String.match не возвращает группы захвата, когда есть флаг g, просто массив элементов с индексом 0 каждого соответствия, который представляет собой всю совпадающую строку.(См. Раздел 15.5.4.10 из спецификации .)

По существу:

var re, match, html;

re = /<a href="(.*?)">[^<]+<\/a>/g;
html = 'Testing <a href="http://yahoo.com">one two three</a> <a href="http://google.com">one two three</a> foo';

re.lastIndex = 0; // Work around literal bug in some implementations
for (match = re.exec(html); match; match = re.exec()) {
  display(match[1]);
}

Живой пример

Но это разбор HTML с регулярными выражениями. Здесь есть драконы.


Обновите re драконов, вот краткий список вещей, которые победят это регулярное выражение, с макушки моей головы:

  1. Все, кроме ровно одного пробела между a и href, например два пробела вместо одного, разрыв строки, class='foo' и т. Д. И т. Д. И т. Д..
  2. Использование одинарных кавычек, а не двойных кавычек вокруг атрибута href.
  3. Совсем не использование кавычек вокруг атрибута href.
  4. Все, что послеатрибут href, который также использует двойные кавычки, например:

    <a href="http://google.com" class="foo">
    

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

...