用于链接字符串中URL的C#代码

时间:2009-04-16 21:28:01

标签: c# asp.net regex linkify

有没有人有任何好的c#代码(和正则表达式)来解析字符串并“链接”字符串中的任何网址?

7 个答案:

答案 0 :(得分:44)

这是一个非常简单的任务,你可以使用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>");

您可能不仅对创建链接感兴趣,还对缩短网址感兴趣。这是一篇关于这个主题的好文章:

另见

答案 1 :(得分:11)

很好,经过大量的研究,以及几次尝试修复时间

  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. 这样的parenthisis
  4. 长网址如: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
  5. 我们现在正在使用这个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;
        }
    

答案 2 :(得分:6)

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;
}

答案 3 :(得分:4)

这不是那么容易,因为你可以阅读blog post by Jeff Atwood。检测URL的结束位置尤其困难。

例如,是否是URL的尾部括号部分:

  • HTTP://en.wikipedia.org/wiki/PCTools(CentralPointSoftware)
  • 括号中的网址(http://en.wikipedia.org)更多文字

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

答案 4 :(得分:1)

找到了正则表达式  http://daringfireball.net/2010/07/improved_regex_for_matching_urls

对我来说,看起来非常好。杰夫阿特伍德解决方案不处理很多情况。 josefresno似乎在处理所有案件。但是,当我试图理解它时(如果有任何支持请求),我的大脑就会沸腾。

答案 5 :(得分:1)

有课程:

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

答案 6 :(得分:0)

这对我有用:

str = Regex.Replace(str,
                @"((http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&amp;:/~\+#]*[\w\-\@?^=%&amp;/~\+#])?)",
                "<a target='_blank' href='$1'>$1</a>");