Есть ли у кого-нибудь хороший код С# (и регулярные выражения), который будет анализировать строку и "связывать" любые URL-адреса, которые могут быть в строке?
Код С# для связывания URL-адресов в строке
Ответ 1
Это довольно простая задача, которую вы можете выполнить с помощью Regex и готового к регулярному выражению:
Что-то вроде:
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\-\._\?\,\'/\\\+&%\$#\=~])*$",
"<a href=\"$1\">$1</a>");
Вам также может быть интересно не только создавать ссылки, но и сокращать URL-адреса. Вот хорошая статья на эту тему:
См. также:
- Регулятор регулярных выражений в MSDN
- Преобразование URL-адреса в ссылку на С# с использованием регулярных выражений
- Regex найти URL-адрес в тексте и сделать его ссылкой
- Regex.Replace Method в MSDN
- Проблема с URL Джеффом Этвудом
- Разбор URL-адресов с регулярными выражениями и объектом регулярных выражений
- Форматировать URL-адреса в строке в HTML-ссылки на С#
- Автоматически гиперссылка URL и электронная почта на страницах ASP.NET с С#
Ответ 2
хорошо, после большого количества исследований по этому вопросу и нескольких попыток исправить времена, когда
- люди входят в http://www.sitename.com и www.sitename.com в том же сообщении
- исправления для parenthisis вроде (http://www.sitename.com) и http://msdn.microsoft.com/en-us/library/aa752574(vs.85).aspx
- длинные 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;
}
Ответ 3
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( " ", " " );
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;
}
Ответ 4
Это не так просто, как вы можете прочитать в этом блоге Джеффа Этвуда. Особенно сложно определить, где заканчивается URL.
Например, это конечная часть скобки URL-адреса или нет:
- Http://en.wikipedia.org/wiki/PCTools (CentralPointSoftware)
- URL в скобках (http://en.wikipedia.org) больше текста
В первом случае скобки являются частью URL-адреса. Во втором случае это не так!
Ответ 5
Найдены следующие регулярные выражения http://daringfireball.net/2010/07/improved_regex_for_matching_urls
для меня выглядит очень хорошо. Решение Джеффа Этвуда не справляется со многими случаями. josefresno, кажется, я обрабатываю все случаи. Но когда я попытался это понять (в случае любых запросов поддержки), мой мозг кипел.
Ответ 6
Существует класс:
public class TextLink
{
#region Properties
public const string BeginPattern = "((http|https)://)?(www.)?";
public const string MiddlePattern = @"([a-z0-9\-]*\.)+[a-z]+(:[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;
}
Тестовые случаи:
[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());
}