C # code para enlazar urls en una cadena

¿Alguien tiene algún buen código de c # (y expresiones regulares) que analizará una cadena y “vinculará” las URL que puedan estar en la cadena?

Es una tarea bastante simple que puedes lograr con Regex y una expresión regular lista para usar de:

Algo como:

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\-\._\?\,\'/\\\+&%\$#\=~])*$", "$1"); 

También puede estar interesado no solo en crear enlaces sino también en acortar URL. Aquí hay un buen artículo sobre este tema:

  • Resuelva y acorte las URL en C #

Ver también :

  • Entorno de trabajo de expresión regular en MSDN
  • Convirtiendo una URL en un enlace en C # usando expresiones regulares
  • Regex para encontrar la URL dentro del texto y hacerlos como un enlace
  • Método Regex.Replace en MSDN
  • El problema con las URL por Jeff Atwood
  • Análisis de URL con expresiones regulares y el objeto Regex
  • Formatea las URL en cadena a los enlaces HTML en C #
  • Automáticamente hipervínculo URL y correo electrónico en páginas ASP.NET con C #

bueno, después de mucha investigación sobre esto, y varios bashs para corregir los tiempos cuando

  1. las personas ingresan en http://www.sitename.com y http://www.sitename.com en la misma publicación
  2. correcciones para parenthisis como ( http://www.sitename.com ) y http://msdn.microsoft.com/en-us/library/aa752574(vs.85).aspx
  3. URL largas como: 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

ahora estamos usando esta extensión HtmlHelper … pensé en compartirla y recibir algún comentario:

  private static Regex regExHttpLinks = new Regex(@"(?< =\()\b(https?://|www\.)[-A-Za-z0-9+&@#/%?=~_()|!:,.;]*[-A-Za-z0-9+&@#/%=~_()|](?=\))|(?<=(?[=~|_#]))\b(https?://|www\.)[-A-Za-z0-9+&@#/%?=~_()|!:,.;]*[-A-Za-z0-9+&@#/%=~_()|](?=\k)|\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, "
"); // 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("{1}", temp.Replace(".", periodReplacement).ToLower(), linkMatches[i].ToString().Replace(".", periodReplacement))); } // Clear out period replacement html = html.Replace(periodReplacement, "."); return html; }

No es tan fácil como puedes leer en esta publicación de blog de Jeff Atwood . Es especialmente difícil detectar dónde termina una URL.

Por ejemplo, es el paréntesis final parte de la URL o no:

  • http: //en.wikipedia.org/wiki/PCTools (CentralPointSoftware)
  • una URL entre paréntesis (http: //en.wikipedia.org) más texto

En el primer caso, los paréntesis son parte de la URL. En el segundo caso, ¡no lo son!

He encontrado la siguiente expresión regular http://daringfireball.net/2010/07/improved_regex_for_matching_urls

para mí se ve muy bien. La solución de Jeff Atwood no maneja muchos casos. josefresno me parece manejar todos los casos. Pero cuando intenté entenderlo (en caso de alguna solicitud de soporte) mi cerebro se hirvió.

Hay clase:

 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 } 

Úselo en este método:

 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("{1}", textLink, textLink.OriginalInput) : textLink.OriginalInput; }); return result; } 

Casos de prueba:

 [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()); }