【问题标题】:.NET Regex parsing of the newline character.NET 正则表达式解析换行符
【发布时间】:2009-12-25 15:51:31
【问题描述】:

我遇到了一些问题。 在我的字符串中可以有一个特殊字符/换行符'\r\n'

我的正则表达式的一部分:

string sRegex = "(?<string>\"+.*\"|'+.*')";

我应该如何修改这个正则表达式以从我的字符串中排除换行符?

感谢您的帮助。

【问题讨论】:

  • C# 中的匈牙利命名,对吧?
  • 如果您可以包含您想要匹配/排除的示例,这将有所帮助。
  • 也许“s”代表正则表达式应该匹配的字符串,而不是正则表达式字符串本身。无论如何,人们可以希望。 ;)
  • 这里是我需要解析的源代码:"Cells[89, 6].Value = \"Some text in russian,25,,13. //;55771;some \r\ntext in.russian.;55771\""

标签: .net regex newline


【解决方案1】:

在大多数语言中(我认为除了 Ruby),多行解析必须显式启用。通过多行解析,我的意思是明确地包括换行符,而不是隐式地在换行符上终止匹配。

在 dotnet 中你想做的:

Regex.Match("string", "regex", RegexOptions.Multiline) 

并且“正则表达式”必须包含带有明确说明的换行符的字符串,例如

"regex\nnewline"

这将匹配内部 2 行:

hello
regex
newline
world

【讨论】:

    【解决方案2】:

    我认为没有足够的信息来完全回答您的问题,但我认为我们可以为您提供足够的信息来自己解决问题。

    查看 Regex 工作台 (http://code.msdn.microsoft.com/RegexWorkbench)。它是找出正确正则表达式的好工具。提供的二进制文件适用于非常旧的 .NET,但您可以重新编译它。

    查看RegexOptions 枚举(http://msdn.microsoft.com/en-us/library/system.text.regularexpressions.regexoptions(VS.71).aspx),尤其是RegexOptions.MultiLine。这可能是你需要的东西。

    有两种方法可以指定选项:RegexOptions 和“内联结构”(http://msdn.microsoft.com/en-us/library/yd1hzczs(VS.71).aspx)。例如,MultiLine 可以指定为:

    string sRegex = "(?<string>\"+.*\"|'+.*')?m";
    

    一些补充说明:

    我对正则表达式使用逐字字符串,因为\ 已经是正则表达式中的转义字符,并且必须进行双重转义会使事情变得混乱。

    我宁愿将我的正则表达式存储在 Regex 对象中而不是字符串中,因为它的类型更丰富。对我来说,一个例外是当我编写字符串来创建一个新的正则表达式时。在这种情况下,我调用变量fooRegexText 来说明这一点。

    我发现任何复杂的正则表达式都难以阅读。我在正则表达式中使用空格来帮助我可怜的大脑(使用IgnorePatternWhitespace)。

    应用这些,我会写:

            Regex regex = new Regex(
    @"(?mx) # MultiLine, IgnorePatternWhitespace
        (?<string>
            ""+.*""
                |
            '+.*'
        )
    ");
    

    【讨论】:

      【解决方案3】:

      您是说仅当引用的字符串包含换行符时才匹配?如果是这样,您不必做任何特别的事情,因为默认情况下点与换行符不匹配。除了开引号后的+(这对我来说没有意义)之外,您的正则表达式应该可以正常工作。但我同意 Jay 的建议,即您使用逐字字符串文字来编写正则表达式:

      Regex sRegex = new Regex(@"(?<string>"".*""|'.*')");
      

      需要注意的是贪婪。例如,如果在同一行上有两个字符串声明,像这样:

      var s1 = "foo", s2 = "bar";
      

      ...正则表达式将找到一个匹配项"foo", s2 = "bar",您希望它分别匹配"foo""bar"。为避免这种情况,您可以使用非贪婪量词:

      Regex sRegex = new Regex(@"(?<string>"".*?""|'.*?')");
      

      如果您确实想要匹配带有换行符的字符串,您可以使用Singleline 选项,它会修改点的行为,使其能够匹配换行符。

      Regex sRegex = new Regex(@"(?<string>"".*?""|'.*?')",
                               RegexOptions.Singleline);
      

      ...或者您可以使用 inline 修饰符:

      Regex sRegex = new Regex(@"(?s)(?<string>"".*?""|'.*?')");
      

      请注意,当您在单行模式下使用点时,使用非贪婪量词尤为重要,因为潜在匹配不再局限于单行。但这里有另一种更有效且更可预测的替代方案:

      Regex sRegex = new Regex(@"(?<string>""[^""]*""|'[^']*')");
      

      没有必要用这个正则表达式指定单行模式,因为你没有使用点元字符。否定字符类[^"] 匹配除引号以外的任何字符——包括换行符。


      最后,我想谈谈Multiline 选项,因为它似乎有很多困惑。人们倾向于认为,只要目标文本由多行组成(即,只要它包含换行符),就必须使用它。这是一个自然的假设,但事实并非如此。

      所有多行模式所做的只是改变开始和结束锚点^$ 的行为。通常它们只匹配整个字符串的开头和结尾,但如果您打开多行模式,它们也会匹配字符串中逻辑行的开头和结尾。例如,给定一个这样声明的字符串:

      "fee fie\nfoe fum"
      

      如果您在默认模式下搜索正则表达式 ^\w+,您将得到一个匹配项:fee。但是如果你切换到多行模式,你会得到两个:feefoe。同样,\w+$ 在默认模式下仅匹配 fum,但在多行模式下匹配 fiefum。无论您处于何种模式:单行、多行或默认模式,您始终可以匹配文字 \n

      人们还倾向于认为单行和多行是相互排斥的,但事实并非如此。我什至看到有人说单行是默认模式。也不是真的。 Singleline 改变点的行为(.),Multiline 改变锚点的行为(^$);就是这样。

      【讨论】:

        【解决方案4】:

        你可以试试这样的:

        string sRegex = "(?<string>\"+(.*[\r\n]*)\"|'+(.*[\r\n]*)*')";
        

        它应该覆盖这样的字符串

        "Akim
        Khalilov
        StackOverflow"
        

        我确信这个正则表达式可以优化。

        因为您没有提供示例文本,所以我可能在这里尝试解决不同的问题。

        【讨论】:

          猜你喜欢
          • 2020-09-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-07-08
          • 2014-07-25
          • 1970-01-01
          • 2011-02-21
          • 1970-01-01
          相关资源
          最近更新 更多