如何创建重复的非捕获组?

时间:2017-11-30 16:28:21

标签: c# regex

我正在尝试创建我认为是重复的非捕获组,而我无法弄清楚如何。

简单来说,我想匹配:

任何数字都是

  • 在任何数量的不包含空格的块之前,但不仅仅是一个数字。
  • 后跟任意数量的不包含空格的块,但不仅仅是一个数字。

Here就是我尝试过的:

模式:(?:\ w。)+(\ d +)(?:。\ w +)+

测试集:

- (IBAction)UpdateICC:(id)sender {

    NSColorSpace *acs = [NSColorSpace adobeRGB1998ColorSpace];
    NSColorSpace *scs = [NSColorSpace sRGBColorSpace];
    NSColorSpace *dcs = [NSColorSpace deviceRGBColorSpace];

    if(_ICCBox.state == NSOnState)
    {
        [_theWindow setColorSpace:scs];
    }
    else
    {
        [_theWindow setColorSpace:dcs];
    }

    [[NSNotificationCenter defaultCenter] postNotificationName:NSWindowDidChangeScreenNotification object:_theWindow];
    // In some cases additional call needed:
    [_theWindow.contentView viewDidChangeBackingProperties];
}

我希望它只匹配:

3.AAA
AAA.BBB
AAA.3.BBB
AAA.3.B555B
AAA.3.BBB.4
AAA.3.BBB.4.CCC
AAA.3.BBB.CCC
AAA.3.BBB.CCC.4
AAA.3.BBB.CCC.4.DDD
ZZZ.AAA.3.BBB
ZZZ.AAA.3.BBB.4
ZZZ.AAA.3.BBB.4.CCC
ZZZ.AAA.3.BBB.CCC
ZZZ.AAA.3.BBB.CCC.4
ZZZ.AAA.3.BBB.CCC.4.DDD

注意:我看到其他一些帖子提出同样的问题,但我不能使用答案,因为它们都像是“不是试图重复一个组,只是匹配'这个',它将适用于你的具体案例“。

2 个答案:

答案 0 :(得分:2)

代码

See regex in use here

^(?:(?!(?:\.|^)\d+\.)\S)+\.\d+\.(?:(?!\.\d+(?:\.|$))\S)+$

结果

输入

3.AAA
AAA.BBB
AAA.3.BBB
AAA.3.B555B
AAA.3.BBB.4
AAA.3.BBB.4.CCC
AAA.3.BBB.CCC
AAA.3.BBB.CCC.4
AAA.3.BBB.CCC.4.DDD
ZZZ.AAA.3.BBB
ZZZ.AAA.3.BBB.4
ZZZ.AAA.3.BBB.4.CCC
ZZZ.AAA.3.BBB.CCC
ZZZ.AAA.3.BBB.CCC.4
ZZZ.AAA.3.BBB.CCC.4.DDD

输出

AAA.3.BBB
AAA.3.B555B
AAA.3.BBB.CCC
ZZZ.AAA.3.BBB
ZZZ.AAA.3.BBB.CCC

说明

  • ^在行首处断言位置
  • (?:(?!(?:\.|^)\d+\.)\S)+匹配以下一次或多次
    • (?!(?:\.|^)\d+\.)否定前瞻确保后续内容不匹配
      • (?:\.|^)匹配以下任一项
        • \.匹配文字点字符.
        • ^在行首处断言位置
      • \d+匹配一个或多个数字
      • \.匹配文字点字符.
    • \S匹配任何非空白字符
  • \.匹配文字点字符.
  • \d+匹配一个或多个数字
  • \.匹配文字点字符.
  • (?:(?!\.\d+(?:\.|$))\S)+匹配以下一次或多次
    • (?!\.\d+(?:\.|$))否定前瞻确保后续内容不匹配
      • \.匹配文字点字符.
      • \d+匹配一个或多个数字
      • (?:\.|$)匹配以下任一项
        • \.匹配文字点字符.
        • $断言行尾的位置
    • \S匹配任何非空白字符
  • $断言行尾的位置

答案 1 :(得分:1)

有一个更简单的解决方案:

^(?:(?!\d+\.)\w+\.)+\d+(?:\.(?!\d+(?=\.|$))\w+)+$

请参阅.NET regex demo(因为它是一个多行演示,\r?必须在$之前添加,在匹配独立字符串时没有必要。)

<强>详情

  • ^ - 字符串开头
  • (?:(?!\d+\.)\w+\.)+ - 由于(?:...)+而导致的任何1个字符字符(字母,数字,_)的1次或多次出现(由于\w+)所有数字后跟一个点(注意,仅匹配字母和数字,您需要使用[\w-[_]][^\W_]代替\w如果您真的在匹配甚至可能包含符号或标点符号的块之后,请将\w替换为[^\s.] - 任何字符,但只有空格或点)
  • \d+ - 一位或多位
  • (?:\.(?!\d+(?=\.|$))\w+)+ - 一次或多次出现
    • \. - 一个点
    • (?!\d+(?=\.|$)) - 未跟随1位数字(\d+),后跟点或字符串结尾
    • \w+ - 一个或多个单词字符
  • $ - 字符串结束。

C# demo

using System.Collections.Generic;
using System.Text.RegularExpressions;
public class Test
{
    public static void Main()
    {
        var lst = new List<string> {"3.AAA", "AAA.BBB", "AAA.3.BBB", "AAA.3.B555B", "AAA.3.BBB.4", 
            "AAA.3.BBB.4.CCC", "AAA.3.BBB.CCC", "AAA.3.BBB.CCC.4", "AAA.3.BBB.CCC.4.DDD",
            "ZZZ.AAA.3.BBB","ZZZ.AAA.3.BBB.4","ZZZ.AAA.3.BBB.4.CCC", "ZZZ.AAA.3.BBB.CCC",
            "ZZZ.AAA.3.BBB.CCC.4", "ZZZ.AAA.3.BBB.CCC.4.DDD"};
        var rx = new Regex(@"^(?:(?!\d+\.)[^\s.]+\.)+\d+(?:\.(?!\d+(?=\.|$))[^\s.]+)+$", 
            RegexOptions.Compiled | RegexOptions.ECMAScript);
        foreach (var s in lst) 
        {
            if (rx.IsMatch(s))
                Console.WriteLine(s);
        }
    }       
}

结果:

AAA.3.BBB
AAA.3.B555B
AAA.3.BBB.CCC
ZZZ.AAA.3.BBB
ZZZ.AAA.3.BBB.CCC