C#的Regex.Matches返回的数组顺序是否保证与文本顺序一致?

4
我正在使用Regex.Matches()从一个大型文本文件中解析一堆匹配项。
是否有任何关于此函数的文档保证Matches数组中的第一项对应于文本中的第一个匹配项,Matches数组中的第二项对应于文本中的第二个匹配项,依此类推?
基于Regex.Match的文档,这似乎是强烈暗示的,但我找不到证据表明Regex.Matches将始终按照它们在文本中被发现的顺序返回匹配项。
编辑
我发现了一个很棒的网站,允许您浏览.NET源代码。
所以从这里开始:http://referencesource.microsoft.com/#System/regex/system/text/regularexpressions/Regex.cs,8d8851eac21ceb80 我们看到matches返回一个新的MatchCollection,这并没有做什么,因为它延迟执行直到被使用。 http://referencesource.microsoft.com/#System/regex/system/text/regularexpressions/RegexMatchCollection.cs,682620f47b442b05,references 我们看到MatchCollection的主要数据结构是ArrayList,保证了顺序。
    _regex = regex;
            _input = input;
            _beginning = beginning;
            _length = length;
            _startat = startat;
            _prevlen = -1;
#if SILVERLIGHT
            _matches = new List<Match>();
#else
            _matches = new ArrayList();
#endif
            _done = false;

GetMatch函数按照文本顺序运行正则表达式,并将每个匹配项添加到主ArrayList中。

Match match;

    do {
        match = _regex.Run(false, _prevlen, _input, _beginning, _length, _startat);

        if (!match.Success) {
            _done = true;
            return null;
        }

        _matches.Add(match);

这对我来说已经足够保证了。
2个回答

5
虽然MSDN没有明确说明,但很明显匹配总是按顺序进行。 MSDN描述了MatchCollection对象如何进行惰性加载。由于正则表达式模式始终以线性方式处理(从左到右或从右到左),很难想象它们会按任何其他顺序进行惰性加载。
例如,这是来自this MSDN article的摘录:
“MatchCollection对象在需要时按匹配逐个填充。它相当于正则表达式引擎重复调用Regex.Match方法并将每个匹配项添加到集合中。当通过其GetEnumerator方法访问集合或使用foreach语句(在C#中)或For Each ... Next语句(在Visual Basic中)访问集合时,使用此技术。”
如果它与重复调用match(将上一个匹配的结束位置作为下一个匹配的开始位置传递)相同,则显然意味着它们将按顺序进行。
当您将其与RegexOptions.RightToLeft选项的存在相结合时,它变得更加清晰
默认情况下,正则表达式引擎从左到右搜索。您可以通过使用RegexOptions.RightToLeft选项来反转搜索方向。搜索自动从字符串的最后一个字符位置开始。对于包括起始位置参数的模式匹配方法(例如Regex.Match(String,Int32)),起始位置是要开始搜索的最右字符位置的索引。
即使如此,如果您不信任它,并且必须保证顺序,则可以按Match.Index属性对它们进行排序:
var matches = Regex.Matches(input, pattern).OrderBy(x=>x.Index);

2
始终以从左到右的线性方式进行处理。那么 RegexOptions.RightToLeft 是做什么用的呢? - user4003407
@PetSerAl 好的,没问题 :) - Steven Doggart
你的解决方案很聪明,我可以像那样自己订购。谢谢! - tt9
啊,实现和API之间的区别。API不能保证它,但当前的实现可以(只要您不指定RightToLeft)。我仍然认为API是有意模糊的,因为它在将来可能会更改。因此,如果您从未更新到实现更改的.NET版本,则可以假定它始终按顺序进行。 - Robert McKee
在延迟加载的集合中,很难想象任何其他明智的实现会干扰顺序。 - flq

0

不,没有保证。 它会按照其想要的顺序返回它们,尽管通常会按照发现它们的顺序返回它们。 在某些情况下可能会有一些例外。 如果顺序绝对关键,则根据它们被发现的位置对匹配项进行排序。

话虽如此,我认为除非您使用一些奇怪的负向回溯组合,否则当前实现将始终按照它们在源中的顺序返回它们,但由于文档似乎没有保证,因此可能会在未来更改(如果使用更高效的多线程正则表达式引擎,例如)。 即使是这样,这种类型的更改也很可能会破坏很多东西,因此只能通过某种标志启用。 因此,您可以相当安全地假设,但这可能会改变。


一个赞表示你理解了“guarantee(保证)”这个词的含义。 - Ben McIntyre

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