C#代码链接在一个string中的URL

有没有人有任何良好的C#代码(和正则expression式)将parsing一个string和“链接”可能在string中的任何url?

这是一个非常简单的任务,你可以使用正则expression式和准备去正则expression式:

就像是:

var html = Regex.Replace(html, @"^(http|https|ftp)\://[a-zA-Z0-9\-\.]+" + "\.[a-zA-Z]{2,3}(:[a-zA-Z0-9]*)?/?" + "([a-zA-Z0-9\-\._\?\,\'/\\\+&amp;%\$#\=~])*$", "<a href=\"$1\">$1</a>"); 

您可能也有兴趣不仅在创build链接,但在缩短url。 这是关于这个问题的好文章:

  • 在C#中parsing和缩短url

另见

  • 正则expression式工作台在MSDN
  • 使用正则expression式将URL转换为C#中的链接
  • 正则expression式在文本中查找URL并将其作为链接
  • 在MSDN的Regex.Replace方法
  • 由Jeff Atwood提供的URL的问题
  • 使用正则expression式parsingURL和正则expression式对象
  • 将string中的URL格式设置为C#中的HTML链接
  • 使用C#自动超链接ASP.NET页面中的URL和电子邮件

好吧,经过这方面的大量研究,以及几次尝试修复的时候

  1. 人们进入http://www.sitename.com和www.sitename.com同一篇文章;
  2. 修复了像( http://www.sitename.com )和http://msdn.microsoft.com/en-us/library/aa752574(vs.85).aspx
  3. 长时间的URL: http ://www.amazon.com/gp/product/b000ads62g/ref=s9_simz_gw_s3_p74_t1?pf_rd_m=atvpdkikx0der&pf_rd_s=center-2&pf_rd_r=04eezfszazqzs8xfm9yd&pf_rd_t=101&pf_rd_p=470938631&pf_rd_i=507846

我们现在使用这个HtmlHelper扩展…以为我会分享并得到任何评论:

  private static Regex regExHttpLinks = new Regex(@"(?<=\()\b(https?://|www\.)[-A-Za-z0-9+&@#/%?=~_()|!:,.;]*[-A-Za-z0-9+&@#/%=~_()|](?=\))|(?<=(?<wrap>[=~|_#]))\b(https?://|www\.)[-A-Za-z0-9+&@#/%?=~_()|!:,.;]*[-A-Za-z0-9+&@#/%=~_()|](?=\k<wrap>)|\b(https?://|www\.)[-A-Za-z0-9+&@#/%?=~_()|!:,.;]*[-A-Za-z0-9+&@#/%=~_()|]", RegexOptions.Compiled | RegexOptions.IgnoreCase); public static string Format(this HtmlHelper htmlHelper, string html) { if (string.IsNullOrEmpty(html)) { return html; } html = htmlHelper.Encode(html); html = html.Replace(Environment.NewLine, "<br />"); // replace periods on numeric values that appear to be valid domain names var periodReplacement = "[[[replace:period]]]"; html = Regex.Replace(html, @"(?<=\d)\.(?=\d)", periodReplacement); // create links for matches var linkMatches = regExHttpLinks.Matches(html); for (int i = 0; i < linkMatches.Count; i++) { var temp = linkMatches[i].ToString(); if (!temp.Contains("://")) { temp = "http://" + temp; } html = html.Replace(linkMatches[i].ToString(), String.Format("<a href=\"{0}\" title=\"{0}\">{1}</a>", temp.Replace(".", periodReplacement).ToLower(), linkMatches[i].ToString().Replace(".", periodReplacement))); } // Clear out period replacement html = html.Replace(periodReplacement, "."); return html; } 
 protected string Linkify( string SearchText ) { // this will find links like: // http://www.mysite.com // as well as any links with other characters directly in front of it like: // href="http://www.mysite.com" // you can then use your own logic to determine which links to linkify Regex regx = new Regex( @"\b(((\S+)?)(@|mailto\:|(news|(ht|f)tp(s?))\://)\S+)\b", RegexOptions.IgnoreCase ); SearchText = SearchText.Replace( "&nbsp;", " " ); MatchCollection matches = regx.Matches( SearchText ); foreach ( Match match in matches ) { if ( match.Value.StartsWith( "http" ) ) { // if it starts with anything else then dont linkify -- may already be linked! SearchText = SearchText.Replace( match.Value, "<a href='" + match.Value + "'>" + match.Value + "</a>" ); } } return SearchText; } 

这并不是那么容易,你可以在Jeff Atwood的博客文章中阅读。 特别难以检测URL的结束位置。

例如,是URL的尾部圆括号还是不是:

  • HTTP://en.wikipedia.org/wiki/PCTools(CentralPointSoftware)
  • 一个URL在括号(http://en.wikipedia.org)中更多的文字

在第一种情况下,括号是URL的一部分。 在第二种情况下,他们不是!

find以下正则expression式http://daringfireball.net/2010/07/improved_regex_for_matching_urls

对我来说看起来非常好。 杰夫·阿特伍德解决scheme不处理许多情况下。 约瑟夫斯诺似乎在处理所有的情况。 但是,当我试图理解它(如果有任何支持请求的话),我的脑子就煮了。

有课:

 public class TextLink { #region Properties public const string BeginPattern = "((http|https)://)?(www.)?"; public const string MiddlePattern = @"([a-z0-9\-]*\.)+[az]+(:[0-9]+)?"; public const string EndPattern = @"(/\S*)?"; public static string Pattern { get { return BeginPattern + MiddlePattern + EndPattern; } } public static string ExactPattern { get { return string.Format("^{0}$", Pattern); } } public string OriginalInput { get; private set; } public bool Valid { get; private set; } private bool _isHttps; private string _readyLink; #endregion #region Constructor public TextLink(string input) { this.OriginalInput = input; var text = Regex.Replace(input, @"(^\s)|(\s$)", "", RegexOptions.IgnoreCase); Valid = Regex.IsMatch(text, ExactPattern); if (Valid) { _isHttps = Regex.IsMatch(text, "^https:", RegexOptions.IgnoreCase); // clear begin: _readyLink = Regex.Replace(text, BeginPattern, "", RegexOptions.IgnoreCase); // HTTPS if (_isHttps) { _readyLink = "https://www." + _readyLink; } // Default else { _readyLink = "http://www." + _readyLink; } } } #endregion #region Methods public override string ToString() { return _readyLink; } #endregion } 

在这个方法中使用它:

 public static string ReplaceUrls(string input) { var result = Regex.Replace(input.ToSafeString(), TextLink.Pattern, match => { var textLink = new TextLink(match.Value); return textLink.Valid ? string.Format("<a href=\"{0}\" target=\"_blank\">{1}</a>", textLink, textLink.OriginalInput) : textLink.OriginalInput; }); return result; } 

testing用例:

 [TestMethod] public void RegexUtil_TextLink_Parsing() { Assert.IsTrue(new TextLink("smthing.com").Valid); Assert.IsTrue(new TextLink("www.smthing.com/").Valid); Assert.IsTrue(new TextLink("http://smthing.com").Valid); Assert.IsTrue(new TextLink("http://www.smthing.com").Valid); Assert.IsTrue(new TextLink("http://www.smthing.com/").Valid); Assert.IsTrue(new TextLink("http://www.smthing.com/publisher").Valid); // port Assert.IsTrue(new TextLink("http://www.smthing.com:80").Valid); Assert.IsTrue(new TextLink("http://www.smthing.com:80/").Valid); // https Assert.IsTrue(new TextLink("https://smthing.com").Valid); Assert.IsFalse(new TextLink("").Valid); Assert.IsFalse(new TextLink("smthing.com.").Valid); Assert.IsFalse(new TextLink("smthing.com-").Valid); } [TestMethod] public void RegexUtil_TextLink_ToString() { // default Assert.AreEqual("http://www.smthing.com", new TextLink("smthing.com").ToString()); Assert.AreEqual("http://www.smthing.com", new TextLink("http://www.smthing.com").ToString()); Assert.AreEqual("http://www.smthing.com/", new TextLink("smthing.com/").ToString()); Assert.AreEqual("https://www.smthing.com", new TextLink("https://www.smthing.com").ToString()); }