c# - 使用正则表达式从字符串中提取数字组

标签 c# .net regex

我需要转换一个字符串,比如

"[1,2,3,4][5,6,7,8]"

整数组,调整为从零开始而不是从一开始:

{0,1,2,3} {4,5,6,7}

以下规则也适用:

  • 该字符串必须至少包含一组带方括号的数字。
  • 每个组必须至少包含 2 个数字。
  • 每个数字都必须是唯一的(这不是我试图用正则表达式实现的)。
  • 0 无效,但 10、100 等有效。

由于我对正则表达式没有那么多经验,所以我目前使用两个;

@"^(?:\[(?:[1-9]+[\d]*,)+(?:[1-9]+[\d]*){1}\])+$";

@"\[(?:[1-9]+[\d]*,)+(?:[1-9]+[\d]*){1}\]";

我使用第一个检查输入,第二个获取方括号内一组数字的所有匹配项。

然后我使用 .Net 字符串操作来去除方括号并提取数字,解析它们并减去 1 以获得我需要的结果。

我想知道是否可以通过使用捕获来更好地获取数字,但不确定它们是如何工作的。


最终解决方案:

最后我使用了下面的正则表达式来验证输入字符串

@"^(?<set>\[(?:[1-9]\d{0,7}(?:]|,(?=\d))){2,})+$"

agent-j 的模式可以很好地捕获所需的信息,但也可以匹配像“[1,2,3,4][5]”这样的字符串,并且需要我对结果进行一些额外的过滤。

我通过命名组“set”访问捕获并使用第二个简单的正则表达式来提取数字。

'[1-9]\d{0,7}' 通过将数字限制为 99,999,999 并避免溢出异常来简化解析整数。

MatchCollection matches = new Regex(@"^(?<set>\[(?:[1-9]\d{0,7}(?:]|,(?=\d))){2,})+$").Matches(inputText);

if (matches.Count != 1)return;

CaptureCollection captures = matches[0].Groups["set"].Captures;

var resultJArray = new int[captures.Count][];
var numbersRegex =  new Regex(@"\d+");
for (int captureIndex = 0; captureIndex < captures.Count; captureIndex++)
{
    string capture = captures[captureIndex].Value;
    MatchCollection numberMatches = numbersRegex.Matches(capture);
    resultJArray [captureIndex] = new int[numberMatches.Count];
    for (int numberMatchIndex = 0; numberMatchIndex < numberMatches.Count; numberMatchIndex++)
    {
        string number = numberMatches[numberMatchIndex].Value;
        int numberAdjustedToZeroBase = Int32.Parse(number) - 1;
        resultJArray [captureIndex][numberMatchIndex] = numberAdjustedToZeroBase;
    }
}

最佳答案

string input = "[1,2,3,4][5,6,7,8][534,63433,73434,8343434]";
string pattern = @"\G(?:\[(?:(\d+)(?:,|(?=\]))){2,}\])";//\])+$";
MatchCollection matches = Regex.Matches (input, pattern);

首先,任何带普通括号的 (regex) 都是捕获组。这意味着正则表达式引擎将捕获(存储与该组匹配的位置)。为避免这种情况(当您不需要它时,请使用 (?:regex)。我在上面这样做了。

Index 0 是特殊的,它表示整个父级。 IE。 match.Groups[0].Value 始终与 match.Value 和 match.Groups[0].Captures[0].Value 相同。因此,您可以考虑将 Groups 和 Capture 集合从索引 1 开始。

正如您在下面看到的,每个匹配项都包含一个带括号的数字组。您需要使用每场比赛第 1 组的第 1-n 次捕获。

foreach (Match match in matches)
{
   // [1,2]
   // use captures 1-n from the first group.
   for (int i = 1; i < match.Group[1].Captures.Count; i++)
   {
      int number = int.Parse(match.Group[1].Captures[i]);
      if (number == 0)
         throw new Exception ("Cannot be 0.");
   }
}

Match[0] => [1,2,3,4]
  Group[0] => [1,2,3,4]
    Capture[0] => [1,2,3,4]
  Group[1] => 4
    Capture[0] => 1
    Capture[1] => 2
    Capture[2] => 3
    Capture[3] => 4
Match[1] => [5,6,7,8]
  Group[0] => [5,6,7,8]
    Capture[0] => [5,6,7,8]
  Group[1] => 8
    Capture[0] => 5
    Capture[1] => 6
    Capture[2] => 7
    Capture[3] => 8
Match[2] => [534,63433,73434,8343434]
  Group[0] => [534,63433,73434,8343434]
    Capture[0] => [534,63433,73434,8343434]
  Group[1] => 8343434
    Capture[0] => 534
    Capture[1] => 63433
    Capture[2] => 73434
    Capture[3] => 8343434

\G 导致匹配从最后一场比赛开始(所以你不会匹配 [1,2] [3,4]) . {2,} 满足您的要求,即每场比赛至少有 2 个号码。

即使有 0,表达式也会匹配。我建议您将验证与其他非正则表达式的东西放在一起。它将使正则表达式更简单。

关于c# - 使用正则表达式从字符串中提取数字组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6466166/

相关文章:

c# - List<T> 设计模式的名称是什么?如何实现

C# 从文本框中删除最后两个字符

.net - MVC、ViewModel 和验证

c# - 有哪些用于创建通用 SQL Server 查询的 .NET 方法?

c# - 慢 SoapHttpClientProtocol 构造函数

javascript - 为什么这个正则表达式在 javascript 函数之外工作而不是在它的内部?

c# - 使用 MVC ViewContext 渲染 View 时指定样式表媒体

c# - 停止挂同步方法

javascript - 具有重复无序匹配的简单正则表达式

javascript - 根据不同的字符长度使用 Javascript RegExp 拆分字符串