簡體   English   中英

如何使Regex僅捕獲命名的組

[英]How do I make Regex capture only named groups

根據Regex文檔,使用RegexOptions.ExplicitCapture可使Regex僅匹配命名的組,例如(?<groupName>...) ; 但是在實際操作中卻有所不同。

考慮以下幾行代碼:

static void Main(string[] args) {
    Regex r = new Regex(
        @"(?<code>^(?<l1>[\d]{2})/(?<l2>[\d]{3})/(?<l3>[\d]{2})$|^(?<l1>[\d]{2})/(?<l2>[\d]{3})$|(?<l1>^[\d]{2}$))"
        , RegexOptions.ExplicitCapture
    );
    var x = r.Match("32/123/03");
    r.GetGroupNames().ToList().ForEach(gn => {
        Console.WriteLine("GroupName:{0,5} --> Value: {1}", gn, x.Groups[gn].Success ? x.Groups[gn].Value : "");
    });
}

運行此代碼段時,您會看到結果包含一個名為0的組,而我的正則表達式中沒有一個名為0的組!

GroupName:    0 --> Value: 32/123/03  
GroupName: code --> Value: 32/123/03  
GroupName:   l1 --> Value: 32  
GroupName:   l2 --> Value: 123  
GroupName:   l3 --> Value: 03  
Press any key to continue . . .  

有人可以向我解釋這種行為嗎?

總是有第0組:這就是整個比賽。 基於定義組的開頭括號的序號位置,編號的組相對於1。 您的正則表達式(為清晰起見而設置):

(?<code>
  ^
  (?<l1> [\d]{2} )
  /
  (?<l2> [\d]{3} )
  /
  (?<l3> [\d]{2} )
  $
|
  ^
  (?<l1>[\d]{2})
  /
  (?<l2>[\d]{3})
  $
|
   (?<l1> ^[\d]{2} $ )
)

您的表達式將回退,因此您可以考慮簡化正則表達式。 這可能更清晰,更有效:

static Regex rxCode = new Regex(@"
  ^                    # match start-of-line, followed by
  (?<code>             # a mandatory group ('code'), consisting of
    (?<g1> \d\d )      # - 2 decimal digits ('g1'), followed by
    (                  # - an optional group, consisting of
      /                #   - a literal '/', followed by
      (?<g2> \d\d\d )  #   - 3 decimal digits ('g2'), followed by
      (                #   - an optional group, consisting of
        /              #     - a literal '/', followed by
        (?<g3> \d\d )  #     - 2 decimal digits ('g3')
      )?               #     - END: optional group
    )?                 #   - END: optional group
  )                    # - END: named group ('code'), followed by
  $                    # - end-of-line
" , RegexOptions.IgnorePatternWhitespace|RegexOptions.ExplicitCapture );

一旦有了,就可以這樣:

string[] texts = { "12" , "12/345" , "12/345/67" , } ;

foreach ( string text in texts )
{
  Match m = rxCode.Match( text ) ;
  Console.WriteLine("{0}: match was {1}" , text , m.Success ? "successful" : "NOT successful" ) ;
  if ( m.Success )
  {
    Console.WriteLine( "  code: {0}" , m.Groups["code"].Value ) ;
    Console.WriteLine( "  g1: {0}" , m.Groups["g1"].Value ) ;
    Console.WriteLine( "  g2: {0}" , m.Groups["g2"].Value ) ;
    Console.WriteLine( "  g3: {0}" , m.Groups["g3"].Value ) ;
  }
}

產生預期

12: match was successful
  code: 12
  g1: 12
  g2:
  g3:
12/345: match was successful
  code: 12/345
  g1: 12
  g2: 345
  g3:
12/345/67: match was successful
  code: 12/345/67
  g1: 12
  g2: 345
  g3: 67

命名

^(?<l1>[\d]{2})/(?<l2>[\d]{3})/(?<l3>[\d]{2})$|^(?<l1>[\d]{2})/(?<l2>[\d]{3})$|(?<l1>^[\d]{2}$)

在此處輸入圖片說明

試試這個(我從您的正則表達式中刪除第一組)- 參見演示

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM