从字符串中删除所有的a标签。

4
我有一个由用户输入的字符串。他们可以添加尽可能多的链接,但我们只希望某些用户能够点击链接。我要做的是将任何a标签替换为其中的纯文本。如果只有一个链接,我已经成功地完成了这个任务,但是当有多个链接时,我无法解决如何处理。
这是我目前所拥有的,并尝试了许多变化来达到这个目标:
url_text = text.split("<a").last.split("</a>").first.split('>').last
text.gsub! /<a.+a>/m, url_text

但它只适用于标签的第一个实例。

我收到的字符串看起来像这样:

text = <div>blah blah blah.<br /><br /></div>\r\n<div><a href=\"http://www.google.com\">Google</a><br />Another link: <br /> <a href=\"http://www.test.com\">Test Link</a><br /><br /></div>"

我希望它能说: 咕噜咕噜咕噜。 谷歌 另一个链接: 测试链接
任何帮助都将不胜感激。如果您需要更多的代码或信息,请告诉我。

3
必须...... **不要使用正则表达式解析HTML**。小马儿回家了,但是你编写的代码可能无法正确处理所有边缘情况,并且通常让用户输入任意HTML是一个非常糟糕的主意——这将让你的系统容易受到XSS攻击。 - Tom Lord
一个更好的想法是使用HTML解析器显式地列出特定的HTML标签(也许为不同的用户使用不同的列表),而不是使用正则表达式。https://edgeapi.rubyonrails.org/classes/ActionView/Helpers/SanitizeHelper.html#method-i-sanitize -- 这个方法可能是你所需要的。 - Tom Lord
@TomLord - 很好的观点,这就是我在问,想着一定有更好的方法。只有超级用户才能输入它,并且它来自tinymce,所以他们不会自己添加HTML。 - Georgeheap
使用所见即所得编辑器并不能保护您免受恶意用户的攻击。用户仍然可以在表单中提交任意数据。但是,如果您完全信任用户,那么(与大多数事情一样)安全性就不再是一个问题。 - Tom Lord
4个回答

5
你可以使用 strip_tags(用于删除所有标签)或strip_links(仅删除链接)。
在Rails控制台中:
> text = '<div>blah blah blah.<br /><br /></div>\r\n<div><a href=\"http://www.google.com\">Google</a><br />Another link: <br /> <a href=\"http://www.test.com\">Test Link</a><br /><br /></div>'
=> "<div>blah blah blah.<br /><br /></div>\\r\\n<div><a href=\\\"http://www.google.com\\\">Google</a><br />Another link: <br /> <a href=\\\"http://www.test.com\\\">Test Link</a><br /><br /></div>"
> helper.strip_tags(text)
=> "blah blah blah.\\r\\nGoogleAnother link:  Test Link"

我选择了strip_links,因为我想保留其他标签。谢谢! - Georgeheap

3
使用Rails助手
ActionView::Base.full_sanitizer.sanitize('text = <div>blah blah blah.<br /><br /></div>\r\n<div><a href=\"http://www.google.com\">Google</a><br />Another link: <br /> <a href=\"http://www.test.com\">Test Link</a><br /><br /></div>"
')

"text = blah blah blah.\\r\\nGoogleAnother link:  Test Link\"\n" 

这也会删除ERB标签和它们之间的任何内容吗? - zasman

2

@mrzasa似乎已经破解了,但是如果你想知道为什么正则表达式不起作用,那是因为它太贪婪了。

使用懒惰操作符意味着扫描尽可能返回最少数量的符合条件的字符。

以下将懒惰操作符添加到搜索中,我相信它可以按照您的意图工作:

text = "<div>blah blah blah.<br /><br /></div>\r\n<div><a href=\"http://www.google.com\">Google</a><br />Another link: <br /> <a href=\"http://www.test.com\">Test Link</a><br /><br /></div><div>blah blah blah.<br /><br /></div>\r\n<div><a href=\"http://www.google.com\">Google</a><br />Another link: <br /> <a href=\"http://www.test.com\">Test Link</a><br /><br /></div>"
text.gsub(/<a.*?>(.+?)<\/a>/, '\1')

# => "<div>blah blah blah.<br /><br /></div>\r\n<div>Google<br />Another link: <br /> Test Link<br /><br /></div><div>blah blah blah.<br /><br /></div>\r\n<div>Google<br />Another link: <br /> Test Link<br /><br /></div>"

gsub 的第二个参数 '\1' 会简单地替换为第一个匹配项。

希望这对您有所帮助,并提供了一种灵活的选项,如果您更愿意使用正则表达式。


2
使用有限字符集比懒惰操作符更好:/<a[^>]*>([^<]+)<\/a>/。我在博客文章中进行了描述。 - mrzasa
啊,太好了,谢谢 @mrzasa,感谢您的反馈。我会仔细阅读你的链接,并在将来自己实现。 - SRack
如果您有任何问题,请在Medium上留下评论,我很乐意回答! - mrzasa

0
根据文档strip_tagsActionView::Helpers::SanitizeHelper模块的一个方法。对我来说,只需要在我的类中包含这个模块,然后就可以像这样使用它的方法:

strip_tags(your_text_with_html)

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