如何在C#正则表达式中使用行内修饰符?

20
2个回答

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

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

// 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]+");

另外,您还可以使用模式修饰符span语法,使用冒号:和分组括号,仅将修饰符限定于该组:

// case sensitive, then case-insensitive match
Regex MyRegex = new Regex(@"(?-i:[a-z]+)(?i:[k-n]+)");
你可以同时使用多个修饰符,如 (?is-m:text),或者在另一个修饰符之后,如果你觉得更清晰的话,可以这样写 (?i)(?s)(?-m)text(我不这么做)。当你使用开/关语法时,请注意修饰符会一直起作用,直到下一次切换或正则表达式结束。相反,使用被修饰的区间后,将恢复默认行为。
最后:.NET 中允许的修饰符是(使用减号来反转模式): x 允许空格和注释
s 单行模式
m 多行模式
i 不区分大小写
n 仅允许显式捕获(仅限于 .NET)

1
谢谢。那么如果我想使用多个修饰符,我只需要使用 (?imsx) 而不是 (?i),比如说? - Aillyn
@aillyn,是的,完全正确。 - Abel

8

使用方式如下:

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

在模式中加入(?<option>:<pattern>)来添加内联选项。在这种情况下,选项是"IgnoreCase"。

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

@"(?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个组,因为它使用了(?<H> hydrogen )
接下来,请注意对第二个模式进行修改,以在结尾处使用(?-x)|oxide。由于在氢捕获后禁用了IgnorePatternWhitespace,因此直到在模式中稍后打开(?x)之前,剩余部分的模式必须正确形成,不能有额外的空格(与第一个模式进行比较)。这没有实际目的,只是展示内联选项的深入使用,以演示它们实际上何时会起作用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接