如何使用JavaScript正则表达式替换href中的所有内容?

4

我的文本内容大致如下:

<a href="http://example.com/test this now">Stuff</a>

More stuff

<a href="http://example.com/more?stuff goes here">more</a>

我希望用一个函数替换href中的内容,使得只有URL部分被进行URL编码。

我该如何实现?

更新:这是我尝试过的:

postdata.comment.content = postdata.comment.content.replace(/href=\"(.+?)\"/g, function(match, p1) {
    return encodeURI(p1);
});

没有达到我的期望。

期望的结果是:

<a href="http%3A%2F%2Fexample.com%2Ftest%20this%20now">Stuff</a>

More stuff

<a href="http%3A%2F%2Fexample.com%2Fmore%3Fstuff%20goes%20here">more</a>

你想修改这两个链接中的哪一个?具体期望的结果是什么? - Oriol
$(pattern).attr('href', 'http://youpi.test/bidule'); - Pierre Emmanuel Lallemant
没有jQuery。我需要纯JS。 - Shamoon
锚点标签在您访问它们之前是否呈现在DOM中,还是您试图操作内存中的字符串?我99%确定Oriole的答案是正确的方法,而不是您接受的答案。 - MonkeyZeus
5个回答

8
正则表达式匹配完整的属性 href="....",但替换只使用编码后的URL,并使用 encodeURIComponent() 对完整URL进行编码。
var string = '<a href="http://example.com/test this now">Stuff</a>';

string = string.replace(/href="(.*?)"/, function(m, $1) {
    return 'href="' + encodeURIComponent($1) + '"';
    //      ^^^^^^                     ^
});

var str = `<a href="http://example.com/test this now">Stuff</a>

More stuff

<a href="http://example.com/more?stuff goes here">more</a>`;

str = str.replace(/href="(.*?)"/g, (m, $1) => 'href="' + encodeURIComponent($1) + '"');

console.log(str);
document.body.textContent = str;


我可以使用这个来替换所有的链接吗? - Shamoon
@Shamoon 是的,使用正则表达式上的 g 标志将替换所有链接,正如我创建的演示中所看到的那样。 - Tushar

6

关于编码,您可以使用encodeURIComponent函数:

var links = document.querySelectorAll('a');
for(var i=0; i<links.length; ++i)
  links[i].href = encodeURIComponent(links[i].href);
<a href="http://example.com/test this now">Stuff</a>
More stuff
<a href="http://example.com/more?stuff goes here">more</a>

如果您只有一个HTML字符串而不是DOM元素,请使用DOM解析器而不是正则表达式进行解析。请参考此链接

var codeString = '<a href="http://example.com/test this now">Stuff</a>\nMore stuff\n<a href="http://example.com/more?stuff goes here">more</a>';
var doc = new DOMParser().parseFromString(codeString, "text/html");
var links = doc.querySelectorAll('a');
for(var i=0; i<links.length; ++i)
  links[i].href = encodeURIComponent(links[i].href);
document.querySelector('code').textContent = doc.body.innerHTML;
<pre><code></code></pre>

请注意,如果您完全编码URL,则将其视为相对URL。

而不是使用 new DOMParser().parseFromString(codeString, "text/html");,你可以使用 (function(){ this.innerHTML = html; [...] }).bind(document.createElement('div'))(html)(这可能会更快一些)。 - Ismael Miguel
@IsmaelMiguel 是的,但只有在字符串是可信的情况下才可以。请尝试使用 '<img src="//" onerror="alert(\'You are pwned!\')" />' 的方法。 - Oriol
非常好的观点。给你20个赞!我不知道当没有元素添加到DOM时,Javascript会运行。 - Ismael Miguel

4

这段代码运行在哪里?如果你有一个DOM对象,那么最好使用DOM循环来遍历document.links或者document.querySelectorAll("a")而不是在HTML上使用正则表达式。此外,你可能不想对所有内容进行编码,只需对搜索部分进行编码即可。

var allLinks = document.querySelectorAll("a");
for (var i=0;i<allLinks.length;i++) {
   var search = allLinks[i].search;
   if (search) {
     allLinks[i].search="?"+search.substring(1).replace(/stuff/,encodeURIComponent("something"));
   }
}

如果你确实想要有编码的href,那么:
for (var i=0;i<allLinks.length;i++) {
   var href = allLinks[i].href;
   if (href) {
     allLinks[i].href=href.replace(/stuff/,encodeURIComponent("something"));
   }
}

从问题中可以很清楚地看出,OP想要对整个URL进行编码。 - cat
是的,http%3A%2F%2Fexample.com%2Ftest%20this%20now 对大多数事情来说可能毫无价值,但这是原帖作者想要的。 - cat
1
他认为自己想要的东西。无论如何,搜索一下“什么是X/Y问题”-已更新以包括href。 - mplungjan

4

免责声明:不要使用正则表达式解析HTML
(原因太多,无法一一列举..)

但是,如果您坚持要这样做,这可能会起作用。

查找 /(<[\w:]+(?:[^>"']|"[^"]*"|'[^']*')*?\shref\s*=\s*)(?:(['"])([\S\s]*?)\2)((?:"[\S\s]*?"|'[\S\s]*?'|[^>]*?)+>)/

替换为 $1$2 + someEncoding( $3 ) + $2$4

扩展:

 (                             # (1 start)
      < [\w:]+ 
      (?: [^>"'] | " [^"]* " | ' [^']* ' )*?
      \s 
      href \s* = \s* 
 )                             # (1 end)
 (?:
      ( ['"] )                      # (2)
      (                             # (3 start)
           [\S\s]*? 
      )                             # (3 end)
      \2 
 )
 (                             # (4 start)
      (?: " [\S\s]*? " | ' [\S\s]*? ' | [^>]*? )+
      >
 )                             # (4 end)

2
这里有太多原因无法列举。正则表达式解析之歌将扼杀凡人的声音,从这个领域中我能看到它,你能看到吗?它是美丽的,最终扑灭了人类的谎言,一切都失去了,所有的一切都失去了,小马他来了,他来了,他来了,灵液渗透了我的脸,我的脸,哦,天哪,不,不,不要停止,天使不是真实的,ZA̡͊͠͝LGΌ ISͮ̂҉̯͈͕̹̘̱ TO͇̹̺ͅƝ̴ȳ̳ TH̘Ë͖́̉ ͠P̯͍̭O̚​N̐Y̡ H̸̡̪̯ͨ͊̽̅̾̎Ȩ̬̩̾͛ͪ̈́̀́͘ ̶̧̨̱̹̭̯ͧ̾ͬC̷̙̲̝͖ͭ̏ͥͮ͟Oͮ͏̮̪̝͍M̲̖͊̒ͪͩͬ̚̚͜Ȇ̴̟̟͙̞ͩ͌͝S̨̥̫͎̭ͯ̿̔̀ͅ - cat
那是你需要的唯一原因。 - cat

2

你期望的字符串"http%3A%2F%2Fexample.com%2Ftest%20this%20now"对应着encodeURIComponent("http://example.com/test this now")函数操作,而不是encodeURI函数:

var str = '<a href="http://example.com/test this now">Stuff</a>More stuff<a href="http://example.com/more?stuff goes here">more</a>';
str = str.replace(/href=\"(.+?)\"/g, function (m, p1) {
    return encodeURIComponent(p1);
});

console.log(str);
// <a http%3A%2F%2Fexample.com%2Ftest%20this%20now>Stuff</a>More stuff<a http%3A%2F%2Fexample.com%2Fmore%3Fstuff%20goes%20here>more</a>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接