In our optimized Regex.Split loop, we failed to update runtextstart, which means the \G anchor (aka starting where the previous match ended).
return;
}
+ // Now that we've matched successfully, update the starting position to reflect
+ // the current position, just as Match.NextMatch() would pass in _textpos as textstart.
+ runtextstart = runtextpos;
+
// Reset state for another iteration.
runtrackpos = runtrack!.Length;
runstackpos = runstack!.Length;
// The .NET Foundation licenses this file to you under the MIT license.
using System.Globalization;
+using System.Linq;
using Xunit;
namespace System.Text.RegularExpressions.Tests
}
+ // https://docs.microsoft.com/en-us/dotnet/standard/base-types/anchors-in-regular-expressions#contiguous-matches-g
+ [Theory]
+ [InlineData(RegexOptions.None)]
+ [InlineData(RegexOptions.Compiled)]
+ public void Docs_Anchors_ContiguousMatches(RegexOptions options)
+ {
+ const string Input = "capybara,squirrel,chipmunk,porcupine";
+ const string Pattern = @"\G(\w+\s?\w*),?";
+ string[] expected = new[] { "capybara", "squirrel", "chipmunk", "porcupine" };
+
+ Match m = Regex.Match(Input, Pattern, options);
+
+ string[] actual = new string[4];
+ for (int i = 0; i < actual.Length; i++)
+ {
+ Assert.True(m.Success);
+ actual[i] = m.Groups[1].Value;
+ m = m.NextMatch();
+ }
+ Assert.False(m.Success);
+ Assert.Equal(expected, actual);
+
+ Assert.Equal(
+ ",arabypac,lerriuqs,knumpihcenipucrop",
+ Regex.Replace(Input, Pattern, m => string.Concat(m.Value.Reverse())));
+ }
+
//
// These patterns come from real-world customer usages
yield return new object[] { "([1-9])([1-9])([1-9])def", "abc123def!", "$+", RegexOptions.RightToLeft, -1, 10, "abc3!" };
yield return new object[] { "([1-9])([1-9])([1-9])def", "abc123def!", "$_", RegexOptions.RightToLeft, -1, 10, "abcabc123def!!" };
+
+ // Anchors
+ yield return new object[] { @"\Ga", "aaaaa", "b", RegexOptions.None, 5, 0, "bbbbb" };
}
[Theory]
yield return new object[] { @"\d", "1a2b3c4d5e6f7g8h9i0k", RegexOptions.RightToLeft, 10, 20, new string[] { "1a", "b", "c", "d", "e", "f", "g", "h", "i", "k" } };
yield return new object[] { @"\d", "1a2b3c4d5e6f7g8h9i0k", RegexOptions.RightToLeft, 2, 20, new string[] { "1a2b3c4d5e6f7g8h9i", "k" } };
yield return new object[] { @"\d", "1a2b3c4d5e6f7g8h9i0k", RegexOptions.RightToLeft, 1, 20, new string[] { "1a2b3c4d5e6f7g8h9i0k" } };
+
+ // Anchors
+ yield return new object[] { @"(?<=\G..)(?=..)", "aabbccdd", RegexOptions.None, 8, 0, new string[] { "aa", "bb", "cc", "dd" } };
}
[Theory]
public void Split(string pattern, string input, RegexOptions options, int count, int start, string[] expected)
{
bool isDefaultStart = RegexHelpers.IsDefaultStart(input, options, start);
- bool isDefaultCount = RegexHelpers.IsDefaultStart(input, options, count);
+ bool isDefaultCount = RegexHelpers.IsDefaultCount(input, options, count);
if (options == RegexOptions.None)
{
// Use Split(string), Split(string, string), Split(string, int) or Split(string, int, int)