【问题标题】:How to use inline modifiers in C# regex?如何在 C# 正则表达式中使用内联修饰符?
【发布时间】:2010-08-22 15:34:10
【问题描述】:

如何使用内联修饰符代替RegexOptions.Option

例如:

Regex MyRegex = new Regex(@"[a-z]+", RegexOptions.IgnoreCase);

如何使用内联字符 i 重写它?

http://msdn.microsoft.com/en-us/library/yd1hzczs.aspx

【问题讨论】:

    标签: c# .net regex


    【解决方案1】:

    您可以按如下方式使用内联修饰符:

    // case insensitive match
    Regex MyRegex = new Regex(@"(?i)[a-z]+");  // case insensitive match
    

    或者,通过添加减号来反转修饰符的含义:

    // case sensitive match
    Regex MyRegex = new Regex(@"(?-i)[a-z]+");  // case sensitive match
    

    或者,打开和关闭它们:

    // case sensitive, then case-insensitive match
    Regex MyRegex = new Regex(@"(?-i)[a-z]+(?i)[k-n]+");
    

    或者,您可以使用 mode-modifier span 语法,使用冒号 : 和分组括号,它将修饰符的范围仅限于该组:

    // case sensitive, then case-insensitive match
    Regex MyRegex = new Regex(@"(?-i:[a-z]+)(?i:[k-n]+)");
    

    您可以像(?is-m:text) 那样一次性使用多个修饰符,或者如果您发现更清晰的(?i)(?s)(?-m)text(我不知道),可以一个接一个地使用。当您使用开/关切换语法时,请注意修饰符在下一次切换或正则表达式结束之前有效。相反,使用模式修改的 span,在 span 之后将应用默认行为。

    最后:the allowed modifiers in .NET are(使用减号反转模式):

    x 允许空格和 cmets
    s 单行模式
    m 多行模式
    i 不区分大小写
    n 只允许显式捕获 (. NET 特定)

    【讨论】:

    • 谢谢。因此,如果我想使用多个修饰符,我只需使用(?imsx) 而不是(?i),例如?
    • @aillyn,是的,正是
    【解决方案2】:

    以这种方式使用它:

    Regex MyRegex = new Regex(@"(?i:[a-z]+)");
    

    使用 (?<option>:<pattern>) 为您的模式添加前缀 inline 选项。在这种情况下,IgnoreCase 的选项是“i”。

    通过在上面指定一个冒号,您将选项设置为该模式。要使该选项适用于整个模式,您可以在开头单独设置它:

    @"(?i)[a-z]+"
    

    也可以使用多个选项并打开和关闭它们:

    // On: IgnoreCase, ExplicitCapture. Off: IgnorePatternWhitespace
    @"(?in-x)[a-z]+"
    

    这允许模式灵活地在正则表达式的不同点启用/禁用选项,而在整个模式上使用 RegexOptions 时这是不可能的。

    这里有一个稍微深入的例子。我鼓励您使用它来了解选项何时生效。

    string input = "H2O (water) is named Dihydrogen Monoxide or Hydrogen Hydroxide. The H represents a hydrogen atom, and O is an Oxide atom.";
    
    // n = explicit captures
    // x = ignore pattern whitespace
    // -i = remove ignorecase option
    string pattern = @"di?(?nx-i) ( hydrogen ) | oxide";
    var matches = Regex.Matches(input, pattern, RegexOptions.IgnoreCase);
    Console.WriteLine("Total Matches: " + matches.Count);
    foreach (Match match in matches)
    {
        Console.WriteLine("Match: {0} - Groups: {1}", match.Value, match.Groups[1].Captures.Count);
    }
    
    Console.WriteLine();
    
    // n = explicit captures
    // x = ignore pattern whitespace
    // -i = remove ignorecase option
    // -x = remove ignore pattern whitespace
    pattern = @"di?(?nx-i) (?<H> hydrogen ) (?-x)|oxide";
    matches = Regex.Matches(input, pattern, RegexOptions.IgnoreCase);
    Console.WriteLine("Total Matches: " + matches.Count);
    foreach (Match match in matches)
    {
        Console.WriteLine("Match: {0} - Groups: {1}", match.Value, match.Groups["H"].Captures.Count);
    }
    

    上面的输出是:

    Total Matches: 3
    Match: Dihydrogen - Groups: 0
    Match: oxide - Groups: 0
    Match: oxide - Groups: 0
    
    Total Matches: 3
    Match: Dihydrogen - Groups: 1
    Match: oxide - Groups: 0
    Match: oxide - Groups: 0
    

    在这两种模式中都使用了RegexOptions.IgnoreCase,它允许“di”不区分大小写,从而匹配“Dihydrogen”(大写 D)。由于显式捕获已打开,第一个示例无法为( hydrogen ) 提供任何组,因为它不使用命名组,这是显式捕获的要求。第二个模式确实有 1 个组,因为它使用 (?&lt;H&gt; hydrogen )

    接下来,请注意第二个模式被修改为在末尾使用(?-x)|oxide。由于 IgnorePatternWhitespace 在氢捕获后被禁用,因此模式的其余部分必须通过在模式中稍后打开 (?x) 之前没有额外的空格(与第一个模式相比)来正确形成。这并没有真正的目的,只是展示了内联选项的深入用法,以演示它们何时真正起作用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多