【问题标题】:Regex replace doesn't replace all occurrences正则表达式替换不会替换所有出现
【发布时间】:2013-04-16 22:24:50
【问题描述】:

我使用下面的正则表达式替换两个单词之间的文本。它有效,只是它跳过了其中一些。下面粘贴的是一个示例。

var EditedHtml = Regex.Replace(htmlText, @"<script(.*?)</script>", ""); 

html文本:

 <head>
   <script src=" https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>
   <script src=" https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/jquery-ui.min.js" type="text/javascript"></script>
   <script src="/AspellWeb/v2/js/dragiframe.js" type="text/javascript"></script>
   <script type="text/javascript">
     var applicationName = '/';
     FullPath = (applicationName.length > 1) ? 'http://localhost:65355' + applicationName : 'http://localhost:65355';
     //FullPath = 'http://localhost:65355';
     GetPath = function (url) {
     return FullPath + url;
   }
   </script>

   <script type="text/javascript" src="../../Scripts/stats.js?"></script>
</head>

<body>
  .......
  <script type="text/javascript">
    function loadAndInit() {

    $(".dvloading").hide();
    if ($.browser.mozilla) {
      if (location.pathname == "/Stats/Reports") {            // This is for local env.
        $("#prntCss").attr("href", "../../../Content/SitePrint_FF.css");
      }
      else {                                                  // This is for DEV/QA/STAGE/PROD env. 
        $("#prntCss").attr("href", "../../Content/SitePrint_FF.css");
      }
    }

  }
  </script>
</body>

EditedHtml:

<head>
  <script type="text/javascript">
    var applicationName = '/';
    FullPath = (applicationName.length > 1) ? 'http://localhost:65355' + applicationName : 'http://localhost:65355';
    //FullPath = 'http://localhost:65355';
    GetPath = function (url) {
      return FullPath + url;
    }
  </script>
</head>

<body>
  .......
  <script type="text/javascript">
    function loadAndInit() {

      $(".dvloading").hide();
      if ($.browser.mozilla) {
        if (location.pathname == "/Stats/Reports") {            // This is for local env.
          $("#prntCss").attr("href", "../../../Content/SitePrint_FF.css");
        }
        else {                                                  // This is for DEV/QA/STAGE/PROD env. 
          $("#prntCss").attr("href", "../../Content/SitePrint_FF.css");
        }
      }

    }
  </script>
</body>

【问题讨论】:

  • 您需要使用RegexOptions.Singleline 来获取 .(dot) 来匹配换行符。
  • 我的第一个猜测是点与换行符不匹配,试试 [.\r\n]*?而是

标签: c# html regex


【解决方案1】:

为什么要使用 Regex 来解析 html。见this

使用像HtmlAgilityPack这样的真正的html解析器会容易得多

HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.Load(filename); //or doc.LoadHtml(HtmlString)

doc.DocumentNode.Descendants()
    .Where(n => n.Name == "script").ToList()
    .ForEach(s => s.Remove());

StringWriter wr = new StringWriter();
doc.Save(wr);
var newhtml = wr.ToString();

【讨论】:

  • doc.load 抛出“路径中的非法字符”异常。应该是 doc.loadHtml()
  • @BumbleBee doc.load 需要一个文件名。如果你想加载一个字符串,那么你应该使用doc.LoadHtml,正如我在答案中评论的那样。
【解决方案2】:

single line mode试试吧:

var EditedHtml = Regex.Replace(
    htmlText, @"<script(.*?)</script>", "", 
    RegexOptions.Singleline); 

文档引用:

指定单行模式。更改点 (.) 的含义,使其匹配每个字符(而不是除 \n 之外的每个字符)。

【讨论】:

  • 为什么人们坚持用正则表达式解析html?只是一个简单的案例&lt;html&gt;&lt;!-- &lt;script --&gt; test&lt;!-- &lt;/script&gt; --&gt;&lt;/html&gt;。我的浏览器为此 html 显示“test”。但是您的正则表达式会从中删除 test
  • 我的正则表达式?这是 OP 的正则表达式。我不会对 OP 为他的工作选择的工具做出判断,我只是在更正他的代码。我同意适当的解析器会更好地提高健壮性,但有时快速而肮脏的正则表达式很好。也许 html 遵循已知格式,也许它是一次性脚本。
【解决方案3】:

试试

var EditedHtml = Regex.Replace(
    htmlText, @"<script(.*?)</script>", "", RegexOptions.Singleline
); 

使用单行模式,以便. 匹配任何字符包括换行符。

【讨论】:

  • 为什么人们坚持用正则表达式解析html?只是一个简单的案例&lt;html&gt;&lt;!-- &lt;script --&gt; test&lt;!-- &lt;/script&gt; --&gt;&lt;/html&gt;。我的浏览器为此 html 显示“test”。但是您的正则表达式会从中删除 test
【解决方案4】:

试试这个:

//(.|\r\n)*: matches every character and/or newline zero or more times
//(.|\r\n)*?: as few times as possible == > you get rid of <script> tags and of their content but you keep the rest of your html
var EditedHtml = Regex.Replace(htmlText, @"<script (.|\r\n)*?</script>", ""); 

希望对你有帮助

参考资料: http://msdn.microsoft.com/en-us/library/az24scfc.aspx

【讨论】:

  • 在 .NET 正则表达式中,. 匹配除换行符 (\n) 之外的所有字符,因此您只需使用 (.|\n)*?。但是正如其他人所建议的那样,使用.*? 并指定Singleline 模式更容易、更高效。
  • 感谢您的反馈,我必须承认为什么使用单行模式更有效,您能否澄清这一点?
  • 首先,您必须将其封装在一个组中,因此每次消耗一个角色时都会产生进出组的额外开销。而且您正在使用 capturing 组,这会增加更多开销。其次,交替本身的效率往往低于等效的字符类。 (.|\n) 非常简单,正则表达式引擎可能可以优化它,但更复杂的替换很容易让引擎崩溃,正如this answer 解释的那样。
  • '恐怕我帮不了你。您可以尝试一个 .NET 特定的讨论论坛;我敢肯定那里有很多。但这绝对不是问这种问题的地方。
猜你喜欢
  • 1970-01-01
  • 2013-06-19
  • 2021-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多