I would like to validate a string of text: .Foo().Bar(20).Baz(Hello)
which could be any number of repetitions of the below pattern:
\.(?<exName>[A-Z,a-z] )\((?<exVal>[^)] )?\)
This correctly provides three matches: ("Foo",empty), ("Bar","20"), and ("Baz","Hello").
Unfortunately, the following test string provides three matches; but in context of my requirements, the string is invalid because of the extra stuff:
.Foo().Bar(20)k.Baz(Hello)hgjfvg
How can I fix this to correctly return three matches, but also include the requirement that the given string must be comprised of one or more matches and no extraneous text?
CodePudding user response:
You can repeat the whole pattern and append anchors, and then in C# get the values of the Group.Captures property to get the values of the named groups.
^(?:\.(?<exName>[A-Za-z] )\((?<exVal>[^()]*)\)) $
See a regex demo | C# demo.
As an example zipping both group collections and matching single lines:
string pattern = @"\A(?:\.(?<exName>[A-Za-z] )\((?<exVal>[^()]*)\)) \z";
var strings = new List<string>() {
".Foo().Bar(20).Baz(Hello)",
".Foo().Bar(30)k.Baz(Hi)hgjfvg",
".Foo(test).Bar(40).Baz(Bye)"
};
foreach (var input in strings)
{
foreach (Match m in Regex.Matches(input, pattern))
{
m.Groups["exName"]
.Captures.Select(c => c.Value)
.Zip(
m.Groups["exVal"].Captures.Select(c => c.Value),
(exName, exVal) => exName " -> " exVal
).ToList()
.ForEach(s => Console.WriteLine(s));
Console.WriteLine("---------------");
}
}
Output
Foo ->
Bar -> 20
Baz -> Hello
------------------------------
Foo -> test
Bar -> 40
Baz -> Bye
------------------------------