捕获重复组

3
我将尝试使用.NET正则表达式解析以下字符串:

我正在尝试使用.NET正则表达式解析以下字符串:

H3Y5NC8E-TGA5B6SB-2NVAQ4E0

使用Split方法返回以下内容:

H3Y5NC8E TGA5B6SB 2NVAQ4E0

我会对每个字符进行特定字符集的验证(请注意字母'I'、'O'、'U'和'W'不在其中),因此不能使用string.Split方法。每组中的字符数和组数都可能不同。我正在使用以下表达式:

([ABCDEFGHJKLMNPQRSTVXYZ0123456789]{8}-?){3}

这将精确匹配3组8个字符。多或少都会导致匹配失败。虽然它可以正确匹配输入,但是当我使用Split方法来提取每个字符组时,我只得到了最后一组。RegexBuddy抱怨我重复了捕获组本身,并建议我在重复的组周围放置一个捕获组。然而,我的尝试都没有达到预期的结果。我一直在尝试像这样的表达式:

(([ABCDEFGHJKLMNPQRSTVXYZ0123456789]{8})-?){4}

但这并不起作用。

由于我在代码中生成正则表达式,因此可以通过组数将其展开,但我希望有一个更优雅的解决方案。


请注意,字符集不包括整个字母表。它是产品激活系统的一部分。因此,任何可能被意外解释为数字或其他字符的字符都被删除了。例如,字母'I'、'O'、'U'和'W'不在字符集中。

连字符是可选的,因为用户不需要输入它们,但如果用户进行了复制和粘贴,则可以存在。

9个回答

5

顺便说一下,您可以用更易读的减去字符类替换[ABCDEFGHJKLMNPQRSTVXYZ0123456789]字符类。

[[A-Z\d]-[IOUW]]

如果您只想匹配像这样的3个组,为什么不在正则表达式中使用此模式3次,并只使用捕获的1、2、3子组来形成新字符串呢?
([[A-Z\d]-[IOUW]]){8}-([[A-Z\d]-[IOUW]]){8}-([[A-Z\d]-[IOUW]]){8}

在PHP中,我会返回(我不知道.NET)
return "$1 $2 $3";

4
我找到了我想要的答案。这是我的工作代码:
    static void Main(string[] args)
    {
        string pattern = @"^\s*((?<group>[ABCDEFGHJKLMNPQRSTVXYZ0123456789]{8})-?){3}\s*$";
        string input = "H3Y5NC8E-TGA5B6SB-2NVAQ4E0";
        Regex re = new Regex(pattern);
        Match m = re.Match(input);

        if (m.Success)
            foreach (Capture c in m.Groups["group"].Captures)
                Console.WriteLine(c.Value);
    }

3

在审查了您的问题和给出的答案后,我想到了以下内容:

RegexOptions options = RegexOptions.None;
Regex regex = new Regex(@"([ABCDEFGHJKLMNPQRSTVXYZ0123456789]{8})", options);
string input = @"H3Y5NC8E-TGA5B6SB-2NVAQ4E0";

MatchCollection matches = regex.Matches(input);
for (int i = 0; i != matches.Count; ++i)
{
    string match = matches[i].Value;
}

由于"-"是可选的,所以您不需要包含它。我不确定您在结尾处使用{4}是用来做什么的?这将根据您想要的内容查找匹配项,然后使用MatchCollection可以访问每个匹配项以重建字符串。


0

抱歉,如果这不是您想要的,但是您的字符串始终使用连字符分隔组,那么您为什么不使用String.Split()方法而不是使用正则表达式呢?

Dim stringArray As Array = someString.Split("-")

0
你可以使用这个模式:
Regex.Split("H3Y5NC8E-TGA5B6SB-2NVAQ4E0", "([ABCDEFGHJKLMNPQRSTVXYZ0123456789]{8}+)-?")

但是你需要从结果数组中过滤掉空字符串。

引用自MSDN

如果多个匹配项相邻,则会在数组中插入一个空字符串。


0

如果你只是想检查组的值,使用group(i).value,那么你只会得到最后一个。然而,如果你想枚举所有捕获到该组的时间,请使用group(2).captures(i).value,如下所示。

system.text.RegularExpressions.Regex.Match("H3Y5NC8E-TGA5B6SB-2NVAQ4E0","(([ABCDEFGHJKLMNPQRSTVXYZ0123456789]+)-?)*").Groups(2).Captures(i).Value

0
为什么要使用正则表达式?如果组总是由“-”分隔,不能使用Split()吗?

0

一个有效块的定义特征是什么?我们需要知道这个才能真正提供帮助。

我的一般建议是,在第一步中验证字符集,然后根据您的期望在单独的方法中进行分割和解析。如果这是在网站/应用程序中,则可以在前端使用ASP Regex验证,然后在后端拆分它。


0

Mike,

你可以在字符组内使用任何字符集。你只需要添加“+”修饰符来捕获所有组。请参考我的先前回答,只需将[A-Z0-9]更改为你需要的内容(例如[A-GHJKLMNPQRSTVXYZ0123456789])。


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