使用正则表达式(.net 和 C#)识别行尾

Posted

技术标签:

【中文标题】使用正则表达式(.net 和 C#)识别行尾【英文标题】:Identify line end with Regex (.net and C#) 【发布时间】:2021-12-08 08:54:19 【问题描述】:

(遇到同样情况的朋友,请注意这个问题可能是.net和C#指定的。见下面Wiktor的回答。)

在问这个问题之前,我已经阅读了许多相关问题(包括:Match linebreaks - \n or \r\n?),但这些答案都没有奏效。

就我而言,我想删除某些代码文件中的所有 //cmets。为了处理 Mac、Unix、Windows 中的文件,我需要一些东西来匹配 // 和 /r、或 /n 或 /r/n 之间的文本。

这里是代码文件的测试内容:

        var text = "int rn = 0; //comment1.0\r\n" +
                   "int r = 0; //comment2.\r" + 
                   "int n = 0; //comment3.\n" + 
                   "end";
        var txt = RemoveLineEndComment();

这里是正则表达式(如果你不是 C charper,请只关注正则表达式):

public static class CommentRemover

    private static readonly Regex RegexRemoveLineEndComment =
        new(@"\/\/.*$", RegexOptions.Multiline);
    public static string RemoveLineEndComment(this string text)
    
        var t = RegexRemoveLineEndComment.Match(text).Value;
        return RegexRemoveLineEndComment.Replace(text, string.Empty);
    

我需要的是 txt = "int rn = 0; \r\nint r = 0; \rint n = 0; \nend"。 以下是正则表达式和相应的结果:

//.*$ => txt="int rn = 0; \nint r = 0; \nend"(缺少int n = 0)

//.*(?=\r\n) => txt="int rn = 0; \r\nint r = 0; //comment2.\rint n = 0; //comment3.\nend" (留下评论2和3)

//.*(?=\r?\n?) => txt="int rn = 0; \nint r = 0; \nend"(缺少int n = 0)

//.*(?=(\r\n|\r|\n)) => txt="int rn = 0; \nint r = 0; \nend" (缺少int n = 0)

//.*(?=[\r\n|\r|\n]) => txt="int rn = 0; \nint r = 0; \nend" (缺少int n = 0) ...

\r 似乎有问题,无法识别。 如果我只使用 \r\n,则正则表达式 "//.*(?=\r\n)" 适用于下面的测试内容:

        var text = "int rn = 0; //comment1.0\r\n" +
                   "int r = 0; //comment2.\r\n" + 
                   "int n = 0; //comment3.\r\n" + 
                   "end";

有人帮帮我吗?感谢您的帮助。

【问题讨论】:

请包含语言标签。 @Barmar 抱歉,我认为这是纯正则表达式问题。但正如 Wiktor 在下面提到的,这可能是一个 .net 问题。如果是这样,我会包括语言标签。 :) 您正在处理的代码是否可能包含例如包含// 序列并且不应被视为cmets的字符串文字? @Damien_The_Unbeliever 否。不在此测试代码中。但它确实发生在我的旧版本中(那个版本中没有使用正则表达式)。可能有类似 text = "//hello" 和 //"hello" 的代码。我对正则表达式不熟悉了,以后会处理这些复杂的情况:) 【参考方案1】:

在 .NET 中,. 模式匹配回车 (CR) 字符。它匹配除 LF 字符之外的任何字符。

请注意,没有选项或修饰符可以重新定义此 . 行为。

因此,您可以使用

var RegexRemoveLineEndComment =  new Regex(@"//[^\r\n]*", RegexOptions.Multiline);

请参阅C# demo。

如果您还想删除// 之前的空格,请在模式开始处添加\s*(任何空格)或[\pZs\t]*(水平空格)。

【讨论】:

感谢您的帮助!但是......奇怪的是,我将您的代码从链接复制到一个新项目中,我又得到了“int rn = 0; \nint r = 0; \nend”(int n = 0 is missing)。 \r 仍然没有被识别,这真的很奇怪。版本之间的差异是否重要? (我正在使用 .net5)我想只用 \r 尝试一些东西,看看是否还有其他线索。再次感谢。 @cheny 由于我没有你的代码,我无法提供更多帮助。我刚刚注意到//[^\r\n]* regex 不需要RegexOptions.Multiline 选项,可以去掉。 啊!终于,我知道到底发生了什么。我确实得到了 txt="int rn = 0; \r\nint r = 0; \rint n = 0; \nend" 的结果,但是当我使用 Console.WriteLine(txt) 时,发生了一些棘手的事情! “\r\n”的意思是“回到当前行的开头,然后下一行,在新的一行打印下面的字母”,而单独的“\r”的意思是“回到当前行的开头,并在当前行打印以下字母”。所以,“int r = 0; " 被 "int n = 0; “!我在代码中放了一个临时参数,发现了。它发生在控制台和文本区域组件中。 再次非常感谢。您将 .NET 与 \r 匹配为 .是关键。 我做到了 :) @Wiktor

以上是关于使用正则表达式(.net 和 C#)识别行尾的主要内容,如果未能解决你的问题,请参考以下文章

了解下C# 正则表达式

如何使用正则表达式匹配从 xml 文件中搜索和替换包含占位符标记的文本。 VB.net 或 C#

正则表达式点到行尾

多个匹配的正则表达式.net c#

使用正则表达式的 ASP.NET C# 客户端和服务器端验证

Python 正则表达式。删除 ':' 之后的所有字符(包括行尾和特定字符串除外)