Regex 如何解决字符串替换失败

Regex 如何解决字符串替换失败,regex,c#-4.0,string-formatting,stringbuilder,Regex,C# 4.0,String Formatting,Stringbuilder,注意:我的问题不是我的链接没有被替换。但是,它正在嵌套。 这是评论 some string with www.google.com/blah/blah also something else www.google.com 当第二个字符串替换完成时,第一个字符串的一部分也是有效的www.google.com/blah/blah,所以它将替换该链接两次 我有一个可以让用户评论的web应用程序。 我正在处理输入字符串,并在页面上显示时将所有链接转换为html链接格式。原始用户输入字符串保留在DB中,

注意:我的问题不是我的链接没有被替换。但是,它正在嵌套。 这是评论

some string with www.google.com/blah/blah also something else www.google.com
当第二个字符串替换完成时,第一个字符串的一部分也是有效的www.google.com/blah/blah,所以它将替换该链接两次

我有一个可以让用户评论的web应用程序。 我正在处理输入字符串,并在页面上显示时将所有链接转换为html链接格式。原始用户输入字符串保留在DB中,不会发生任何事情,因此不会在处理过程中损坏。当我在页面上显示它时,我在上面执行我的功能

现在,这就是我用来用html格式替换所有链接的逻辑

正则表达式所有链接 对于每个匹配项,将链接替换为原始字符串中的html格式版本。 最后显示字符串。 例如:www.google.com在页面显示之前就变成了

这是伟大的工作,直到最近,我的一个客户发布了一个内容与两个来自同一领域的链接

比如说,

www.google.com/images/blahblah www.google.com 我的问题是,当第二次替换字符串时,我正在使用StringBuilder。替换第一个链接也会被替换

因此,首先

www.google.com/images/blahblah
变成

<a href="http://www.google.com/images/blahblah" target="_blank">www.google.com/image/blahblah</a>
那我就用

foreach(Match match in matches)
{
    if(match.value.StartsWith("www.youtube.com/watch"))
    {
         //logic to embed youtube video - this works fine.
    } 
}

//Here I replace all hyperlinks to their <a href> parts
Matches返回一个MatchCollection。匹配。索引就是你要找的

string pattern = @"(https?://)?(?:www(?:\.\w+)+|(?:\w+\.)+(?:com|org|us|net|...))(/\w*)*"; // your pattern here.
foreach (Match match in Regex.Matches (input, pattern))
{
   // Use match.Index and match.Length;
}
但实际上,你可能正在寻找更像这样的东西:

string originalPost = 
   @"Ooh shiney: www.google.com/images/blahblah
   Look here: www.google.com";

string html = Regex.Replace (
   originalPost, patternString, 
   "<a href='http://$1' target='_blank'>$1</a>");
或者,您可以使用matchEvaluator执行更高级的工作,如确保我们不添加双http://

string html = Regex.Replace (
   originalPost, patternString, 
   m => 
      string.Format (
         "<a href='{0}{1}' target='_blank'>{1}</a>",
          m.Value.StartsWith ("http", StringComparison.IgnoreCase) ? "" : "http://",
          m.Value));
Matches返回一个MatchCollection。匹配。索引就是你要找的

string pattern = @"(https?://)?(?:www(?:\.\w+)+|(?:\w+\.)+(?:com|org|us|net|...))(/\w*)*"; // your pattern here.
foreach (Match match in Regex.Matches (input, pattern))
{
   // Use match.Index and match.Length;
}
但实际上,你可能正在寻找更像这样的东西:

string originalPost = 
   @"Ooh shiney: www.google.com/images/blahblah
   Look here: www.google.com";

string html = Regex.Replace (
   originalPost, patternString, 
   "<a href='http://$1' target='_blank'>$1</a>");
或者,您可以使用matchEvaluator执行更高级的工作,如确保我们不添加双http://

string html = Regex.Replace (
   originalPost, patternString, 
   m => 
      string.Format (
         "<a href='{0}{1}' target='_blank'>{1}</a>",
          m.Value.StartsWith ("http", StringComparison.IgnoreCase) ? "" : "http://",
          m.Value));
使用方法,例如:

var result = Regex.Replace(input, pattern, "<a href=\"$0\" target=\"_blank\">$0</a>");
使用方法,例如:

var result = Regex.Replace(input, pattern, "<a href=\"$0\" target=\"_blank\">$0</a>");

扮演魔鬼的倡导者:

因此,您希望更正如下所示的字符串:

www.example.com
www.example.com/foo/bar
www.example.co.tw/baz.moo?foo=1
但是,不是像这样的字符串:

www.example.com
www.example.com/foo/bar
www.example.co.tw/baz.moo?foo=1
www.example.com www.example.com/foo/bar www.example.co.tw/baz.moo?foo=1

我想我是对的。简单的解决方案是,扩展您的正则表达式,使其看起来像URL,并在以下情况下忽略它:

介于a href=和a target=\u blank> 介于target=\u blank>和
扮演魔鬼的倡导者:

因此,您希望更正如下所示的字符串:

www.example.com
www.example.com/foo/bar
www.example.co.tw/baz.moo?foo=1
但是,不是像这样的字符串:

www.example.com
www.example.com/foo/bar
www.example.co.tw/baz.moo?foo=1
www.example.com www.example.com/foo/bar www.example.co.tw/baz.moo?foo=1

我想我是对的。简单的解决方案是,扩展您的正则表达式,使其看起来像URL,并在以下情况下忽略它:

介于a href=和a target=\u blank> 介于target=\u blank>和
我也有同样的需求,这就是我过去几年一直在使用的:

public static string MakeCommentSafe(string strComment)
{
    // Replace carriage return / line feeds with line feeds.  Then HtmlEncode.  Then replace multiple consecutive line feeds with single line feeds.
    strComment = Regex.Replace(System.Web.HttpContext.Current.Server.HtmlEncode(Regex.Replace(strComment, "\r\n", "\n").Replace((char)13, (char)10)), "\n(\n)+", "$1\n");

    // Find all links and make them active
    return Regex.Replace(Regex.Replace(strComment, @"((https?|ftp|gopher|telnet|file|notes|ms-help):((//)|(\\\\))+[\w\d:#@%/;$()~_?\+-=\\\.&]*)", "<a href=\"$1\" target=\"_blank\" rel=\"nofollow\">$1</a>"), "\n", "<br />");
}

这里有个提示。如果您真的希望在页面上有大量注释时能够很好地执行此操作,那么在发布注释时将不安全和安全版本存储在数据库中。这样,在页面上显示每个评论时,您就不必重复调用此函数。

我也有同样的需求,这就是我过去几年一直在使用的功能:

public static string MakeCommentSafe(string strComment)
{
    // Replace carriage return / line feeds with line feeds.  Then HtmlEncode.  Then replace multiple consecutive line feeds with single line feeds.
    strComment = Regex.Replace(System.Web.HttpContext.Current.Server.HtmlEncode(Regex.Replace(strComment, "\r\n", "\n").Replace((char)13, (char)10)), "\n(\n)+", "$1\n");

    // Find all links and make them active
    return Regex.Replace(Regex.Replace(strComment, @"((https?|ftp|gopher|telnet|file|notes|ms-help):((//)|(\\\\))+[\w\d:#@%/;$()~_?\+-=\\\.&]*)", "<a href=\"$1\" target=\"_blank\" rel=\"nofollow\">$1</a>"), "\n", "<br />");
}

这里有个提示。如果您真的希望在页面上有大量注释时能够很好地执行此操作,那么在发布注释时将不安全和安全版本存储在数据库中。这样,在页面上显示每个注释时,您就不必重复调用此函数。

嗨,为什么Regex.Replace嵌套了两次?@ocasthorde-我在每行上一次做几件事。如果你想的话,你当然可以把它分成不同的行。哦,我现在看到了,首先你正在转换链接,然后将新行转换为..嗨,为什么Regex.Replace嵌套了两次?@rocusthorde-我在每行上一次做几件事。如果你愿意,你当然可以把它分成不同的行。哦,我现在看到了,首先你正在转换链接,然后将新行转换为..嗨,这看起来很神奇,只是,我不太明白,我在哪里可以读到更多关于这方面的内容?比如,这里1美元是什么意思?它会取代所有实例吗?什么是matchEvaluator等。1美元将替换为第一组。我应该说0美元会被整场比赛取代。MatchEvaluator是为每个匹配调用的委托-返回要替换匹配的字符串。Hi@aget-j,如果我想在MatchEvaluator中包含https作为条件,比如StartWithHTTP或https@LocustHorde好主意。lambda语法越来越长,所以您可能应该将该逻辑移到一个单独的函数中。顺便说一下,https以http开头-事实上,https确实是从http开始的。我会看看我能做什么。此外,还发现了一个小错误,您的string.Format a href=http://{0}{1}。。。其中包括一个http,并且计算器添加另一个http。它应该只是嗨,这看起来很神奇,只是,我不明白
还有很多,我在哪里可以读到更多关于这方面的信息?比如,这里1美元是什么意思?它会取代所有实例吗?什么是matchEvaluator等。1美元将替换为第一组。我应该说0美元会被整场比赛取代。MatchEvaluator是为每个匹配调用的委托-返回要替换匹配的字符串。Hi@aget-j,如果我想在MatchEvaluator中包含https作为条件,比如StartWithHTTP或https@LocustHorde好主意。lambda语法越来越长,所以您可能应该将该逻辑移到一个单独的函数中。顺便说一下,https以http开头-事实上,https确实是从http开始的。我会看看我能做什么。此外,还发现了一个小错误,您的string.Format a href=http://{0}{1}。。。其中包括一个http,并且计算器添加另一个http。应该只有你好,对不起,我想匹配所有东西。除了匹配链接外,我还在匹配youtube视频,这是链接的一个子集,并将它们转换为视频。嗨,对不起,我想匹配所有内容。除了匹配链接外,我还在匹配youtube视频,这是链接的一个子集,并将它们转换为视频。