регулярное выражение javascript для извлечения текста привязки и URL из тегов привязки - PullRequest
14 голосов
/ 15 декабря 2008

У меня есть абзац текста в переменной javascript с именем 'input_content', и этот текст содержит несколько якорных тегов / ссылок. Я хотел бы сопоставить все теги привязки, извлечь текст привязки и URL-адрес и поместить его в массив, подобный (или похожему) на следующее:

Array
(
    [0] => Array
        (
            [0] => <a href="http://yahoo.com">Yahoo</a>
            [1] => http://yahoo.com
            [2] => Yahoo
        )
    [1] => Array
        (
            [0] => <a href="http://google.com">Google</a>
            [1] => http://google.com
            [2] => Google
        )
)

Я получил трещину (http://pastie.org/339755),, но я зашел в тупик за этим пунктом. Спасибо за помощь!

Ответы [ 6 ]

42 голосов
/ 15 декабря 2008
var matches = [];

input_content.replace(/[^<]*(<a href="([^"]+)">([^<]+)<\/a>)/g, function () {
    matches.push(Array.prototype.slice.call(arguments, 1, 4))
});

Это предполагает, что ваши якоря всегда будут иметь вид <a href="...">...</a>, т.е. он не будет работать, если есть какие-либо другие атрибуты (например, target). Регулярное выражение может быть улучшено, чтобы приспособиться к этому.

Чтобы разбить регулярное выражение:

/ -> start regular expression
  [^<]* -> skip all characters until the first <
  ( -> start capturing first token
    <a href=" -> capture first bit of anchor
    ( -> start capturing second token
        [^"]+ -> capture all characters until a "
    ) -> end capturing second token
    "> -> capture more of the anchor
    ( -> start capturing third token
        [^<]+ -> capture all characters until a <
    ) -> end capturing third token
    <\/a> -> capture last bit of anchor
  ) -> end capturing first token
/g -> end regular expression, add global flag to match all anchors in string

Каждый вызов нашей анонимной функции получит три токена в качестве второго, третьего и четвертого аргументов, а именно аргументы [1], аргументы [2], аргументы [3]:

  • arguments [1] - это полный якорь
  • arguments [2] - это часть href
  • arguments [3] - текст внутри

Мы будем использовать хак для вставки этих трех аргументов в качестве нового массива в наш основной matches массив. Встроенная переменная arguments не является истинным массивом JavaScript, поэтому нам потребуется применить к нему метод split Array, чтобы извлечь нужные элементы:

Array.prototype.slice.call(arguments, 1, 4)

Это извлечет элементы из arguments, начиная с индекса 1 и заканчивая (не включительно) индексом 4.

var input_content = "blah \
    <a href=\"http://yahoo.com\">Yahoo</a> \
    blah \
    <a href=\"http://google.com\">Google</a> \
    blah";

var matches = [];

input_content.replace(/[^<]*(<a href="([^"]+)">([^<]+)<\/a>)/g, function () {
    matches.push(Array.prototype.slice.call(arguments, 1, 4));
});

alert(matches.join("\n"));

Дает:

<a href="http://yahoo.com">Yahoo</a>,http://yahoo.com,Yahoo
<a href="http://google.com">Google</a>,http://google.com,Google
9 голосов
/ 15 декабря 2008

Поскольку вы, вероятно, запускаете javascript в веб-браузере, регулярное выражение кажется плохой идеей для этого. Если абзац изначально пришел со страницы, получите дескриптор контейнера, вызовите .getElementsByTagName(), чтобы получить привязки, а затем извлеките нужные значения таким образом.

Если это невозможно, то создайте новый объект элемента html, присвойте свой текст его свойству .innerHTML, а затем вызовите .getElementsByTagName().

6 голосов
/ 15 декабря 2008

Я думаю, что Джоэл имеет на это право - регулярные выражения печально известны тем, что они плохо играют с разметкой, поскольку просто слишком много возможностей для рассмотрения. Есть ли другие атрибуты для якорных тегов? В каком они порядке? Является ли разделительный пробел всегда одним пробелом? Поскольку у вас уже есть браузер HTML parser , лучше всего использовать его вместо этого.

function getLinks(html) {
    var container = document.createElement("p");
    container.innerHTML = html;

    var anchors = container.getElementsByTagName("a");
    var list = [];

    for (var i = 0; i < anchors.length; i++) {
        var href = anchors[i].href;
        var text = anchors[i].textContent;

        if (text === undefined) text = anchors[i].innerText;

        list.push(['<a href="' + href + '">' + text + '</a>', href, text];
    }

    return list;
}

Это вернет массив, подобный тому, который вы описываете, независимо от того, как хранятся ссылки. Обратите внимание, что вы можете изменить функцию для работы с переданным элементом вместо текста, изменив имя параметра на «контейнер» и удалив первые две строки. Свойство textContent / innerText возвращает текст, отображаемый для ссылки, без какой-либо разметки (полужирный / курсив / шрифт /…). Вы можете заменить .textContent на .innerHTML и удалить внутренний оператор if (), если хотите сохранить разметку.

2 голосов
/ 15 декабря 2008

Я думаю, JQuery будет вашим лучшим выбором. Это не лучший сценарий, и я уверен, что другие могут дать что-то лучше. Но это создает массив именно того, что вы ищете.

<script type="text/javascript">
    // From http://brandonaaron.net Thanks!
    jQuery.fn.outerHTML = function() {
        return $('<div>').append( this.eq(0).clone() ).html();
    };    

    var items = new Array();
    var i = 0;

    $(document).ready(function(){
        $("a").each(function(){
            items[i] = {el:$(this).outerHTML(),href:this.href,text:this.text};
            i++;      
        });
    });

    function showItems(){
        alert(items);
    }

</script>
1 голос
/ 11 сентября 2016

Чтобы извлечь URL:

var pattern = /.href="(.)".*/; var url = string.replace (pattern, '$ 1');

Демо-версия:

//var string = '<a id="btn" target="_blank" class="button" href="https://yourdomainame.com:4089?param=751&amp;2ndparam=2345">Buy Now</a>;'
//uncomment the above as an example of link.outerHTML

var string = link.outerHTML
var pattern = /.*href="(.*)".*/;
var href = string.replace(pattern,'$1');
alert(href)

Для "якорного текста", почему бы не использовать: link.innerHtml

1 голос
/ 14 июля 2016

Для блага поисковиков: я создал что-то, что будет работать с дополнительными атрибутами в теге привязки. Для тех, кто не знаком с Regex, значения в долларах ($ 1 и т. Д.) - это совпадения группы регулярных выражений.

var text = 'This is my <a target="_blank" href="www.google.co.uk">link</a> Text';
var urlPattern = /([^+>]*)[^<]*(<a [^>]*(href="([^>^\"]*)")[^>]*>)([^<]+)(<\/a>)/gi;
var output = text.replace(urlPattern, "$1___$2___$3___$4___$5___$6");
alert(output);

См. Рабочие jsFiddle и regex101 .

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

var returnText = text.replace(urlPattern, function(fullText, beforeLink, anchorContent, href, lnkUrl, linkText, endAnchor){
                    return "The bits you want e.g. linkText";
                });
...