gpt4 book ai didi

.net - 在 .NET 的 RegEx 中,我可以从 Capture 对象获取 Groups 集合吗?

转载 作者:行者123 更新时间:2023-12-02 05:36:49 24 4
gpt4 key购买 nike

.NET 在其正则表达式实现中提供了一个 Capture 集合,因此您可以获得给定重复组的所有实例,而不仅仅是它的最后一个实例。太好了,但我有一个带有子组的重复组,我正在尝试获取子组,因为它们在组下相关,但找不到方法。有什么建议吗?

我查看了许多其他问题,例如:

但我没有找到适用的答案,无论是肯定的(“是的,这就是方法”)或否定的(“不,不能这样做。”)。

举一个人为的例子,假设我有一个输入字符串:

abc d x 1 2 x 3 x 5 6 e fgh

其中“abc”和“fgh”代表我想在较大文档中忽略的文本,“d”和“e”包裹感兴趣的区域,在该感兴趣的区域内,“x n [n]”可以重复任意次数。我感兴趣的是“x”区域中的那些数字对。

所以我使用这个正则表达式模式来解析它:

.*d (?<x>x ((?<fir>\d+) )?((?<sec>\d+) )?)*?e.*

它将在文档中准确地找到一个匹配项,但会多次捕获“x”组。以下是我想要在此示例中提取的三对:

  • 1, 2
  • 3
  • 5、6

但是我怎样才能得到它们呢?我可以执行以下操作(在 C# 中):

using System;
using System.Text;
using System.Text.RegularExpressions;

string input = "abc d x 1 2 x 3 x 5 6 e fgh";
string pattern = @".*d (?<x>x ((?<fir>\d+) )?((?<sec>\d+) )?)*?e.*";
foreach (var x in Regex.Match(input, pattern).Groups["x"].Captures) {
MessageBox.Show(x.ToString());
}

由于我引用组“x”,我得到这些字符串:

  • x 1 2
  • x 3
  • x 5 6

但这并不能让我了解数字本身。所以我可以独立地执行“fir”和“sec”,而不仅仅是“x”:

using System;
using System.Text;
using System.Text.RegularExpressions;

string input = "abc d x 1 2 x 3 x 5 6 e fgh";
string pattern = @".*d (?<x>x ((?<fir>\d+) )?((?<sec>\d+) )?)*?e.*";
Match m = Regex.Match(input, pattern);
foreach (var f in m.Groups["fir"].Captures) {
MessageBox.Show(f.ToString());
}

foreach (var s in m.Groups["sec"].Captures) {
MessageBox.Show(s.ToString());
}

获取:

  • 1
  • 3
  • 5
  • 2
  • 6

但是我无法知道是第二对缺少“4”,而不是其他对中的一对。

那么该怎么办呢?我知道我可以轻松地用 C# 解析它,甚至可以在“x”组上进行第二次正则表达式测试,但由于第一次正则表达式运行已经完成了所有工作并且结果已知,似乎应该有一种方法操纵 Match 对象以从中获取我需要的内容。

请记住,这是一个人为的示例,现实世界的情况有些复杂,因此仅添加额外的 C# 代码会很痛苦。但如果现有的 .NET 对象无法做到这一点,那么我只需要知道这一点,然后我将继续我的方式。

想法?

最佳答案

我不知道是否有完全内置的解决方案,并且在快速搜索后找不到解决方案,但这并不排除存在解决方案的可能性。

我最好的建议是使用 IndexLength 属性来查找匹配的捕获。它看起来不太优雅,但在编写一些扩展方法后你也许能够想出一些相当不错的代码。

var input = "abc d x 1 2 x 3 x 5 6 e fgh";

var pattern = @".*d (?<x>x ((?<fir>\d+) )?((?<sec>\d+) )?)*?e.*";

var match = Regex.Match(input, pattern);

var xs = match.Groups["x"].Captures.Cast<Capture>();

var firs = match.Groups["fir"].Captures.Cast<Capture>();
var secs = match.Groups["sec"].Captures.Cast<Capture>();

Func<Capture, Capture, Boolean> test = (inner, outer) =>
(inner.Index >= outer.Index) &&
(inner.Index < outer.Index + outer.Length);

var result = xs.Select(x => new
{
Fir = firs.FirstOrDefault(f => test(f, x)),
Sec = secs.FirstOrDefault(s => test(s, x))
})
.ToList();

这是使用以下扩展方法的一种可能的解决方案。

internal static class Extensions
{
internal static IEnumerable<Capture> GetCapturesInside(this Match match,
Capture capture, String groupName)
{
var start = capture.Index;
var end = capture.Index + capture.Length;

return match.Groups[groupName]
.Captures
.Cast<Capture>()
.Where(inner => (inner.Index >= start) &&
(inner.Index < end));
}
}

现在您可以按如下方式重写代码。

var input = "abc d x 1 2 x 3 x 5 6 e fgh";

var pattern = @".*d (?<x>x ((?<fir>\d+) )?((?<sec>\d+) )?)*?e.*";

var match = Regex.Match(input, pattern);

foreach (Capture x in match.Groups["x"].Captures)
{
var fir = match.GetCapturesInside(x, "fir").SingleOrDefault();
var sec = match.GetCapturesInside(x, "sec").SingleOrDefault();
}

关于.net - 在 .NET 的 RegEx 中,我可以从 Capture 对象获取 Groups 集合吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13919459/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com