【问题标题】:Regex Not Finding All Matches C# [duplicate]正则表达式未找到所有匹配 C# [重复]
【发布时间】:2018-03-27 14:46:48
【问题描述】:

我研究、测试并使用了 RegEx.101,但无法弄清楚这一点。我花了几个小时在上面。

我正在寻找 16 数字

这是我的正则表达式:"[0-9]{16}"

代码如下:

Regex ItemRegex = new Regex("[0-9]{16}");
// test with a 29 digit number
foreach (Match ItemMatch in ItemRegex.Matches("564654564553314342340968580654"))
{
    i++;
}

我期待多个匹配项,但我只得到前 16 位数字。如何获取从位置 1 开始的前 16 位数字,然后从位置 2 开始的后 16 位数字,然后是第三位,等等?

任何想法、想法、建议或解决方案都将不胜感激并 +1。

【问题讨论】:

  • 这个(?=(\d{16}))?
  • 你的正则表达式没问题,但是你怎么期望有两个 30 个字符的 16 个字符的字符串呢?向您的字符串添加更多数字
  • @MarkBenovsky:一个 29 位数字包含 14 个 16 位数字的子串。
  • @ctwheels 是正确的
  • 如果@ctwheels 是正确的,那么他们应该将其作为答案发布。这样它就可以被赞成和接受以及所有这些事情。 :)

标签: c# regex


【解决方案1】:

正如 ctwheels 在他/她的评论中提到的那样,要获得您想要的重叠匹配,您需要使用一个名为 lookahead assertion 的概念,这是一个表达式,用于在不消耗这些条件的情况下评估是否满足条件人物。这些分别称为正面和负面的超前断言。考虑以下表达式:

\d(?=(\d{15}))

第一个 \d 将匹配单个数字并在表达式中使用该字符。随后是一个肯定的前瞻断言(由(?=expression) 表示),该断言测试该单个数字是否后跟另外 15 个数字,而不消耗这 15 个字符。不使用这些字符意味着表达式可以找到从第一个字符开始的其他匹配项与初始\d 匹配的那个字符之后。所以:

var expression = @"\d(?=(\d{15}))";
var testString = "564654564553314342340968580654";

var regex = new Regex(expression);
foreach (Match match in regex.Matches(testString))
{
    Console.WriteLine($"{match.Groups[0].Value}{match.Groups[1].Value}");
}

在我的Console.WriteLine 中,我汇总了每场比赛中出现的两组内容:第一个是前导数字,第二个是后面的 15 位数字组。上面代码的输出是:

5646545645533143
6465456455331434
4654564553314342
6545645533143423
5456455331434234
4564553314342340
5645533143423409
6455331434234096
4553314342340968
5533143423409685
5331434234096858
3314342340968580
3143423409685806
1434234096858065
4342340968580654

【讨论】:

  • 感谢您的精彩解释!!!
  • 我将答案留在这里,因为文本可能有用,但@ctwheels 答案中的表达更好;我没有意识到您可以将整个事情都放入断言中。所以我也学到了一些东西!谢谢,ctwheels!
  • 你的解释肯定也补充了我的回答,所以+1
【解决方案2】:

See regex in use here

(?=(\d{16}))
  • (?=(\d{16})) 正向前瞻确保以下跟随当前位置
    • (\d{16}) 捕获 16 位到捕获组 1

结果:

5646545645533143
6465456455331434
4654564553314342
6545645533143423
5456455331434234
4564553314342340
5645533143423409
6455331434234096
4553314342340968
5533143423409685
5331434234096858
3314342340968580
3143423409685806
1434234096858065
4342340968580654

那么这是如何工作的呢?好吧,前瞻(?=) 是一个零宽度断言,它检查它包含的子模式是否在字符串中的特定位置匹配。由于我们没有锚定正则表达式,这将尝试匹配字符串中的每个 位置

那么,零宽度断言意味着什么?环顾实际上匹配字符然后放弃匹配,只返回结果:匹配或不匹配。在我们的例子中,我们还在肯定的前瞻断言中添加了一个捕获组,从而允许它捕获结果。我们最终得到的是空匹配(仅匹配 16 位后面的特定位置)和捕获组中的结果(我们的 16 位)。

【讨论】:

  • 耶 -- 谢谢,谢谢 :)
  • 很好,比我的回答简单一点(很好!)。
【解决方案3】:

这是一种没有 RegEx 的方法

// test with a 29 digit number
string input = "564654564553314342340968580654";
for (int i = 0; i < input.Length - 16+1; i++)
{
    string result = string.Concat(input.Skip(i).Take(16));
    if (result.All(x => char.IsDigit(x)))
    {
        Console.WriteLine(result);
    }
}

https://dotnetfiddle.net/igGMSL

【讨论】:

  • 谢谢,但我需要很多匹配项——第一个数字开头的前 16 位数字,第二个数字开头的 16 位数字等等。
猜你喜欢
  • 2015-12-26
  • 2017-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-13
  • 1970-01-01
  • 2013-01-19
  • 2023-03-25
相关资源
最近更新 更多