regex javascript para texto extrato âncora e URL de marcas de âncora
-
21-08-2019 - |
Pergunta
Eu tenho um parágrafo de texto em uma variável javascript chamado 'input_content' e que o texto contém várias marcas de âncora / links. Eu gostaria de combinar todas as marcas de âncora e extrato de texto âncora e URL, e colocá-lo em uma matriz como (ou similar) este:
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 ) )
Eu tomei um crack para ele ( http://pastie.org/339755 ), mas eu estou perplexo além deste ponto. Obrigado pela ajuda!
Solução
var matches = [];
input_content.replace(/[^<]*(<a href="([^"]+)">([^<]+)<\/a>)/g, function () {
matches.push(Array.prototype.slice.call(arguments, 1, 4))
});
Isso pressupõe que suas âncoras sempre estará na forma <a href="...">...</a>
ou seja, não vai funcionar se existem outros atributos (por exemplo, target
). A expressão regular pode ser melhorado para acomodar isso.
Para quebrar a expressão regular:
/ -> 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
Cada chamada para a função anónimo vai receber três sinais como a segunda, terceira e quarta argumentos, nomeadamente argumentos [1], [2] argumentos, argumentos [3]:
- argumentos [1] é toda a âncora
- argumentos [2] é a parte href
- argumentos [3] é o interior texto
Vamos usar um hack para empurrar estes três argumentos como uma nova matriz para a nossa gama matches
principal. O arguments
variável interna não é uma verdadeira matriz JavaScript, por isso vamos ter de aplicar o método split
matriz nele para extrair os itens que queremos:
Array.prototype.slice.call(arguments, 1, 4)
Isto irá extrair itens de arguments
começando no índice 1 e terminando (não incluído) no índice 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"));
Dá:
<a href="http://yahoo.com">Yahoo</a>,http://yahoo.com,Yahoo <a href="http://google.com">Google</a>,http://google.com,Google
Outras dicas
Uma vez que você estiver executando presumivelmente o JavaScript em um navegador web, regex parece ser uma má idéia para isso. Se o parágrafo veio da página em primeiro lugar, obter uma alça para o recipiente, chamada .getElementsByTagName()
para obter as âncoras, e, em seguida, extrair os valores que você quer assim.
Se isso não for possível, então, criar um novo objeto elemento html, atribuir o seu texto a ele de propriedade .innerHTML, e depois chamar .getElementsByTagName()
.
Eu acho que Joel tem o direito dela - expressões regulares são notórios por jogar mal com a marcação, pois há simplesmente demasiado muitas possibilidades a considerar. Existem outros atributos para as marcas de âncora? Que ordem é que eles estão? É o espaço em branco separando sempre um único espaço? Vendo como você já tem HTML de um navegador parser disponíveis, melhor para colocar isso para o trabalho em seu lugar.
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;
}
Isso irá retornar um array como o que você descreve, independentemente de como os links são armazenados. Note que você pode mudar a função para trabalhar com um elemento passado em vez de texto, alterando o nome do parâmetro para "container" e remover as duas primeiras linhas. A propriedade textContent / innerText obtém o texto exibido para o link, despojado de qualquer marcação (negrito / itálico / font / ...). Você poderia substituir .textContent com .innerHTML e remover a instrução interna, se () se você quiser preservar a marcação.
JQuery seria sua melhor aposta. Este não é o melhor roteiro e tenho certeza que os outros podem dar algo melhor. Mas isso cria uma matriz de exatamente o que você está procurando.
<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>
Para extrair o url:
var pattern = /.href="(.)".*/; var url = string.replace (padrão, '$ 1');
Demonstração:
//var string = '<a id="btn" target="_blank" class="button" href="https://yourdomainame.com:4089?param=751&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)
Para "texto âncora", por que não usar:
link.innerHtml
Para o benefício dos pesquisadores: Eu criei algo que irá trabalhar com atributos adicionais na tag âncora. Para aqueles não familiarizados com Regex, o dólar ($ 1 etc) os valores são os jogos de grupo regex.
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);
Veja a trabalhar jsFiddle e regex101 .
Como alternativa, você pode obter informações para fora dos grupos assim:
var returnText = text.replace(urlPattern, function(fullText, beforeLink, anchorContent, href, lnkUrl, linkText, endAnchor){
return "The bits you want e.g. linkText";
});