【问题标题】:Regex to remove trailing whitespace and multiple blank lines正则表达式删除尾随空格和多个空行
【发布时间】:2015-07-29 15:40:28
【问题描述】:

我希望在用 C# 编写的 Visual Studio 2013 扩展中使用正则表达式。

我正在尝试从一行中删除尾随空格,同时保留空行。我还想删除多个空行。应保留现有的行尾(通常是回车换行)。

所以下面的文字(空格显示为下划线):

hello_world__


___hello_world_
__
__
hello_world

会变成:

hello_world

___hello_world

hello_world

我尝试了多种不同的模式来删除尾随空格,但我最终要么不匹配尾随空格,要么丢失了回车符。我还没有尝试删除多个空行。

以下是我目前尝试过的几种模式:

\s+$

(?<=\S)\s+$

【问题讨论】:

  • 严格使用是否需要使用RegEx?有更好的方法来删除字符串末端的符号:TrimEnd 和 TrimStart。对于您的情况: str.TrimEnd(new char[] { '_' })
  • 我并不严格需要使用正则表达式,但我认为它适合我想做的事情。也许我应该详细说明,但我将其应用于活动文档。我正在使用 C#。这不必在单个操作中完成;多次操作就好了。
  • 单次操作会更难做到这一点。但是,它们是 2 个不同的操作,您也不需要 1 个来执行另一个操作。
  • 正则表达式明显TrimEnd慢。

标签: c# .net regex visual-studio-2013


【解决方案1】:

感谢到目前为止的回答。它们都不适合我的需要,但它们帮助我想出了我需要的东西。我认为问题在于 VS2013 中的正则表达式有些奇怪(请参阅Using Regular Expressions in Visual Studio)。这两个操作对我有用:

\ +(?=(\n|\r?$)) 替换为空。

^\r?$(\n|\r\n){2,} 替换为\r\n

【讨论】:

  • VS2013 使用 Dot-Net 正则表达式引擎,并不奇怪。仅供参考,微软(例如 Windows)在他们提供 api 的所有编辑框中都使用 CRLF 翻译。因此,您的正则表达式没有意义。最后,你扯掉了我的表达,自己回答了问题,然后将其标记为正确。
  • 任何人给出的答案都没有真正对我有用。它们都是很好的正则表达式,并且在在线正则表达式测试器中运行良好,但它们在 .NET 或 VS 查找替换工具中对我不起作用。我发布了一个答案,因为我想留下一个适合我的情况的答案,以防它对其他人有用。实际上,替换尾随空格的正则表达式来自@zolo,并在我提供的链接中建议了修改。删除多个空白行的正则表达式我使用几个答案作为灵感放在一起。
  • 我会检查 Visual Studio 是否真的使用 Dot-Net 引擎。微软表示确实如此。当你说它不起作用时,我真的不确定你的意思是什么,因为他们的引擎主要是一个 pcre 引擎,缺少递归并且有一些类额外的构造等。但这里没有涉及,没有..跨度>
【解决方案2】:

删除多个空行和尾随空格

(?:\r\n[\s-[\rn]]*){3,}

并替换为\r\n\r\n

demo

要删除剩余的空格,您可以使用

(?m)[\s-[\r]]+\r?$

demo 2

【讨论】:

  • 你能解释一下这部分吗? [\s-[\r]]
  • 是的。字符类减法是 .NET 特有的功能。对于那些不支持类减法或交集的正则表达式风格,使用否定字符类是一种解决方法。
【解决方案3】:
\ +(?=(\n|$))

任意数量的空格,并在换行符或行尾(字符串/文本中的最后一个字符)之后检查。 (当然需要开启多线和全局模式)

【讨论】:

  • 一件事,这也将匹配here\t\t\t\t
  • 完全正确。我应该只使用“\+”而不是“\s+”。谢谢!
  • 那么\ + 不会让正则表达式匹配超过 1 行
  • regex101.com/r/fF1jE4/1 我不明白你到底是什么意思。检查这里,如果我用错了,请告诉我。
  • 我说错了,你设置了全局标志//g,它找到了3个单独的匹配项。
【解决方案4】:

就像平底船一样,不使用正则表达式,您始终可以通过行尾标记拆分文档,然后使用 TrimEnd 进行反馈(由 Anton Semenov 突出显示)...

(假设一个文本文档读入一个字符串...)

//  Ascertain the linefeed...
string str = "This is a test    \r\nto see if I can force   \ra string to be broken \non multiple lines           \r\n into an array.";
string[] t = str.Split(new string[] { "\r\n", "\r", "\n" } ,StringSplitOptions.RemoveEmptyEntries);
thediv.InnerHtml = str + "<br /><br />";
foreach(string s in t)
{
    thediv.InnerHtml += s.TrimEnd() + "<br />";
}

我根本没有计时,但是如果您希望避免正则表达式的复杂性(如果可以的话,我会这样做 - 见下文*),您应该会发现这个速度足够快,可以做您想做的事情。

* 如果可以,我会避免使用正则表达式。这并不意味着我不使用它。正则表达式有它的位置,但我相信它是相关工作的最后手段,例如遵循格式的复杂灵活字符串 - 替代方案会生成大量代码。将正则表达式保持在最低限度有助于提高代码的可读性。

【讨论】:

    【解决方案5】:

    作为单独的操作 -

    删除任何(?m)[^\S\r\n]+$的尾随空格
    删除带有文本(?m)(?&lt;=\S)[^\S\r\n]+$ 的尾随空白行

    删除重复的空白行(连同空白修剪)

        # Find: (?>\A(?:[^\S\r\n]*\r\n)+)|(?>\r\n(?:[^\S\r\n]*(\r\n)){2,})
        # Replace: $1\r\n
    
    
        (?>
             \A 
             (?: [^\S\r\n]* \r \n )+
        )
     |  
        (?>
             \r \n 
             (?:
                  [^\S\r\n]* 
                  ( \r \n )                     # (1)
             ){2,}
        )
    

    【讨论】:

      【解决方案6】:

      \s 包含换行符,我将只搜索多个空格。我不知道 VS 的具体细节,但希望这样做:

      [" "]*?$
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-04-10
        • 2012-03-20
        • 1970-01-01
        • 1970-01-01
        • 2016-06-17
        • 2019-03-10
        • 2016-05-24
        • 1970-01-01
        相关资源
        最近更新 更多