备用构造

替换构造用于修改正则表达式,以支持 either/or 或条件匹配。 .NET Framework 支持三个替换构造:

  • 使用 | 的模式匹配

  • 使用 (?(表达式)yes|no) 的条件匹配

  • 基于有效捕获组的条件匹配

使用 | 的模式匹配

使用垂直条 (|) 字符可以匹配一系列模式中的任意一个,其中| 字符分隔每个模式。

与正字符类相似,| 字符可用于匹配一组单个字符中的任何一个。 下例使用正字符类和带有 | 字符的 either/or 模式匹配,在字符串中定位出现单词“gray”或“grey”的地方。 在这种情况下, | 字符生成更详细的正则表达式。

Imports System.Text.RegularExpressions

Module Example
   Public Sub Main()
      ' Regular expression using character class.
      Dim pattern1 As String = "\bgr[ae]y\b"
      ' Regular expression using either/or.
      Dim pattern2 As String = "\bgr(a|e)y\b"

      Dim input As String = "The gray wolf blended in among the grey rocks."
      For Each match As Match In Regex.Matches(input, pattern1)
         Console.WriteLine("'{0}' found at position {1}", _
                           match.Value, match.Index)
      Next      
      Console.WriteLine()
      For Each match As Match In Regex.Matches(input, pattern2)
         Console.WriteLine("'{0}' found at position {1}", _
                           match.Value, match.Index)
      Next      
   End Sub
End Module
' The example displays the following output:
'       'gray' found at position 4
'       'grey' found at position 35
'       
'       'gray' found at position 4
'       'grey' found at position 35           
using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      // Regular expression using character class.
      string pattern1 = @"\bgr[ae]y\b";
      // Regular expression using either/or.
      string pattern2 = @"\bgr(a|e)y\b";

      string input = "The gray wolf blended in among the grey rocks.";
      foreach (Match match in Regex.Matches(input, pattern1))
         Console.WriteLine("'{0}' found at position {1}", 
                           match.Value, match.Index);
      Console.WriteLine();
      foreach (Match match in Regex.Matches(input, pattern2))
         Console.WriteLine("'{0}' found at position {1}", 
                           match.Value, match.Index);
   }
}
// The example displays the following output:
//       'gray' found at position 4
//       'grey' found at position 35
//       
//       'gray' found at position 4
//       'grey' found at position 35           

对于使用 | 字符的正则表达式模式 \bgr(a|e)y\b,其含义如下表所示。

模式

说明

\b

在单词边界处开始。

gr

匹配字符“gr”。

(a|e)

匹配“a”或“e”中任一。

y\b

在字边界上匹配“y”。

| 字符还可用于执行具有多个字符或子表达式的 either/or 匹配,其中可以包括字符文本和正则表达式语言元素的任意组合 (字符类不提供此功能)。下例使用 | 字符提取 9 位数的美国 社会保险号码 (SSN),格式为 ddd-dd-dddd,或者提取 9 位数的美国 雇主标识号 (EIN),格式为 dd-ddddddd。

Imports System.Text.RegularExpressions

Module Example
   Public Sub Main()
      Dim pattern As String = "\b(\d{2}-\d{7}|\d{3}-\d{2}-\d{4})\b"
      Dim input As String = "01-9999999 020-333333 777-88-9999"
      Console.WriteLine("Matches for {0}:", pattern)
      For Each match As Match In Regex.Matches(input, pattern)
         Console.WriteLine("   {0} at position {1}", match.Value, match.Index)
      Next   
   End Sub
End Module
' The example displays the following output:
'       Matches for \b(\d{2}-\d{7}|\d{3}-\d{2}-\d{4})\b:
'          01-9999999 at position 0
'          777-88-9999 at position 22
using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = @"\b(\d{2}-\d{7}|\d{3}-\d{2}-\d{4})\b";
      string input = "01-9999999 020-333333 777-88-9999";
      Console.WriteLine("Matches for {0}:", pattern);
      foreach (Match match in Regex.Matches(input, pattern))
         Console.WriteLine("   {0} at position {1}", match.Value, match.Index);
   }
}
// The example displays the following output:
//       Matches for \b(\d{2}-\d{7}|\d{3}-\d{2}-\d{4})\b:
//          01-9999999 at position 0
//          777-88-9999 at position 22

正则表达式模式 \b(\d{2}-\d{7}|\d{3}-\d{2}-\d{4})\b 的含义如下表所示。

模式

说明

\b

在单词边界处开始。

(\d{2}-\d{7}|\d{3}-\d{2}-\d{4})

匹配以下之一:两个十进制数字,后接一个连字符,再接七个十进制数字;或三个十进制数字,后接一个连字符,再接两个十进制数字,再接另一连字符,再接四个十进制数字。

\d

在单词边界处结束匹配。

返回页首

使用表达式的条件匹配

此语言元素尝试根据是否可以匹配初始模式来匹配两种模式之一。 其语法为:

(?(表达式)yes|no)

其中表达式 是要匹配的初始模式;yes 是当表达式 找到匹配项时,要匹配的模式;no 是当表达式 未找到匹配项时,要匹配的模式。 正则表达式引擎将表达式 视为一个零宽度断言;即,正则表达式引擎在计算表达式 之后,不再处理输入流的后续数据。 因此,此构造等同于以下内容:

(?(?=表达式)yes|no)

其中 (?=表达式) 是零宽度断言构造。 (有关更多信息,请参见分组构造。)由于正则表达式引擎将表达式 解释为定位点(零宽度断言),因此表达式 必须是零宽度断言(有关更多信息,请参阅正则表达式中的定位点),或者是也包含在 yes 中的子表达式。 否则,无法匹配 yes 模式。

注意注意

如果表达式 是命名捕获组或带编号的捕获组,则替换构造将被解释为捕获测试;有关更多信息,请参阅下一节基于有效捕获组的条件匹配。换言之,正则表达式引擎不会尝试匹配捕获的子字符串,而是改为测试组是否存在。

下例是使用 | 的 either/or 模式匹配一节中那个示例的另一种形式。 它使用条件匹配来确定单词边界后的前三个字符是否两位数字加一个连字符。 如果是,则尝试匹配美国 雇主标识号 (EIN)。 如果不是,则尝试匹配美国 社会保险号码 (SSN)。

Imports System.Text.RegularExpressions

Module Example
   Public Sub Main()
      Dim pattern As String = "\b(?(\d{2}-)\d{2}-\d{7}|\d{3}-\d{2}-\d{4})\b"
      Dim input As String = "01-9999999 020-333333 777-88-9999"
      Console.WriteLine("Matches for {0}:", pattern)
      For Each match As Match In Regex.Matches(input, pattern)
         Console.WriteLine("   {0} at position {1}", match.Value, match.Index)
      Next   
   End Sub
End Module
' The example displays the following output:
'       Matches for \b(?(\d{2}-)\d{2}-\d{7}|\d{3}-\d{2}-\d{4})\b:
'          01-9999999 at position 0
'          777-88-9999 at position 22
using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = @"\b(?(\d{2}-)\d{2}-\d{7}|\d{3}-\d{2}-\d{4})\b";
      string input = "01-9999999 020-333333 777-88-9999";
      Console.WriteLine("Matches for {0}:", pattern);
      foreach (Match match in Regex.Matches(input, pattern))
         Console.WriteLine("   {0} at position {1}", match.Value, match.Index);
   }
}
// The example displays the following output:
//       Matches for \b(\d{2}-\d{7}|\d{3}-\d{2}-\d{4})\b:
//          01-9999999 at position 0
//          777-88-9999 at position 22

正则表达式模式 \b(?(\d{2}-)\d{2}-\d{7}|\d{3}-\d{2}-\d{4})\b 的含义如下表所示。

模式

说明

\b

在单词边界处开始。

(?(\d{2}-)

确定随后的三个字符是否为两位数字加一个连字符。

\d{2}-\d{7}

如果上一个模式匹配,则匹配两位数字开头,后接一个连字符,再接七位数字。

\d{3}-\d{2}-\d{4}

如果上一个模式不匹配,则匹配三个十进制数字,后接一个连字符,再接两个十进制数字,再接另一个连字符,再接四个十进制数字。

\b

与字边界匹配。

返回页首

基于有效捕获组的条件匹配

此语言元素尝试根据是否可以匹配指定的捕获组来匹配两种模式之一。 其语法为:

(?(名称)yes|no)

(?(数字)yes|no)

其中名称 是捕获组的名称,编号 是捕获组的编号;yes 是当名称 或编号 找到匹配项时,要匹配的表达式;no 是当未找到匹配项时,要匹配的可选表达式。

如果名称 与正则表达式模式中所用捕获组的名称不对应,则替换构造将解释为表达式测试,如上一节中所述。 通常,这意味着表达式 的计算结果为 false。 如果编号 与正则表达式模式中所用带编号的捕获组不对应,则正则表达式引擎引发 ArgumentException

下例是使用 | 的 either/or 模式匹配一节中那个示例的另一种形式。 它使用名为 n2 的捕获组,该捕获组是一个两位数字后接一个连字符。 替换构造测试此捕获组是否已在输入字符串中匹配。 如果是,替换构造将尝试匹配美国 雇主标识号 (EIN)。 如果不是,则尝试匹配美国 社会保险号码 (SSN)。

Imports System.Text.RegularExpressions

Module Example
   Public Sub Main()
      Dim pattern As String = "\b(?<n2>\d{2}-)*(?(n2)\d{7}|\d{3}-\d{2}-\d{4})\b"
      Dim input As String = "01-9999999 020-333333 777-88-9999"
      Console.WriteLine("Matches for {0}:", pattern)
      For Each match As Match In Regex.Matches(input, pattern)
         Console.WriteLine("   {0} at position {1}", match.Value, match.Index)
      Next   
   End Sub
End Module
using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = @"\b(?<n2>\d{2}-)*(?(n2)\d{7}|\d{3}-\d{2}-\d{4})\b";
      string input = "01-9999999 020-333333 777-88-9999";
      Console.WriteLine("Matches for {0}:", pattern);
      foreach (Match match in Regex.Matches(input, pattern))
         Console.WriteLine("   {0} at position {1}", match.Value, match.Index);
   }
}
// The example displays the following output:
//       Matches for \b(?<n2>\d{2}-)*(?(n2)\d{7}|\d{3}-\d{2}-\d{4})\b:
//          01-9999999 at position 0
//          777-88-9999 at position 22

正则表达式模式 \b(?<n2>\d{2}-)*(?(n2)\d{7}|\d{3}-\d{2}-\d{4})\b 的含义如下表所示。

模式

说明

\b

在单词边界处开始。

(?<n2>\d{2}-)*

匹配两个数字(后跟连字符)的零个或一个匹配项。 将此捕获组命名为 n2。

(?(n2)

测试输入字符串中是否有 n2 的匹配项。

)\d{7}

如果找到 n2 的匹配项,则匹配七个十进制数字。

|\d{3}-\d{2}-\d{4}

如果未找到 n2 的匹配项,则匹配三个十进制数字,后接一个连字符,再接两个十进制数字,再接另一个连字符,再接四个十进制数字。

\b

与字边界匹配。

下例显示了此示例的另一种形式,即使用带编号的组而非命名组。 它的正则表达式模式为 \b(\d{2}-)*(?(1)\d{7}|\d{3}-\d{2}-\d{4})\b。

Imports System.Text.RegularExpressions

Module Example
   Public Sub Main()
      Dim pattern As String = "\b(\d{2}-)*(?(1)\d{7}|\d{3}-\d{2}-\d{4})\b"
      Dim input As String = "01-9999999 020-333333 777-88-9999"
      Console.WriteLine("Matches for {0}:", pattern)
      For Each match As Match In Regex.Matches(input, pattern)
         Console.WriteLine("   {0} at position {1}", match.Value, match.Index)
      Next   
   End Sub
End Module
' The example displays the following output:
'       Matches for \b(\d{2}-)*(?(1)\d{7}|\d{3}-\d{2}-\d{4})\b:
'          01-9999999 at position 0
'          777-88-9999 at position 22
using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = @"\b(\d{2}-)*(?(1)\d{7}|\d{3}-\d{2}-\d{4})\b";
      string input = "01-9999999 020-333333 777-88-9999";
      Console.WriteLine("Matches for {0}:", pattern);
      foreach (Match match in Regex.Matches(input, pattern))
         Console.WriteLine("   {0} at position {1}", match.Value, match.Index);
   }
}
// The example display the following output:
//       Matches for \b(\d{2}-)*(?(1)\d{7}|\d{3}-\d{2}-\d{4})\b:
//          01-9999999 at position 0
//          777-88-9999 at position 22

返回页首

请参见

概念

正则表达式语言元素