TL;DR:这是一个可选的解决方案
var str = @"You have {notifications, plural,
zero {no notifications}
one {one notification}
=42 {a universal amount of notifications}
other {# notifications}
}. Have a nice day, {name}!";
// get matches skipping nested curly braces
var matches =
Regex.Matches(str, @"{((?:[^{}]|(?<counter>{)|(?<-counter>}))+(?(counter)(?!)))}");
var results = matches.Cast<Match>().Select(m => m.Groups[1].Value).Distinct()
.Select(v => Regex.Match(v, @"^\w+").Value) // take 1st word
.ToList();
导致(在调试时从 Visual Studio Locals 窗口复制)
results Count = 2 System.Collections.Generic.List<string>
[0] "notifications"
[1] "name"
...原始答案如下...
关于原问题中的当前解决方案需要注意的一点:
-
. 的使用与换行符不匹配,因此这是它当前匹配嵌套值的原因之一(请参阅此source)
如果我理解你的目标,这篇文章是对相关问题和解决方案的一个很好的解释和演示:
(本文解决了原始问题中提到的主要挑战——嵌套花括号)
https://blogs.msdn.microsoft.com/timart/2013/05/14/nestedrecursive-regex-and-net-balancing-groups-detect-a-function-with-a-regex/
从那篇文章中,我建议将以下模式作为可选解决方案:
var str = @"You have {notifications, plural,
zero {no notifications}
one {one notification}
=42 {a universal amount of notifications}
other {# notifications}
}. Have a nice day, {name}!";
// get matches skipping nested curly braces
var matches =
Regex.Matches(str, @"{((?:[^{}]|(?<counter>{)|(?<-counter>}))+(?(counter)(?!)))}");
var results = matches.Cast<Match>().Select(m => m.Groups[1].Value).Distinct().ToList();
导致(在调试时从 Visual Studio Locals 窗口复制)
results Count = 2 System.Collections.Generic.List<string>
[0] "notifications, plural,\r\n zero {no notifications}\r\n one {one notification}\r\n =42 {a universal amount of notifications}\r\n other {# notifications}\r\n "
[1] "name"
(或者如果您要将这些结果打印到控制台):
// Result 0 would look like:
notifications, plural,
zero {no notifications}
one {one notification}
=42 {a universal amount of notifications}
other {# notifications}
// Result 1 would look like:
name
更新
我回过头来意识到这个问题只要求单个单词作为结果。
然后从每个结果中取出第一个单词
(我用附加的 select 语句重复上面的 sn-p 以显示完整的解决方案)
var str = @"You have {notifications, plural,
zero {no notifications}
one {one notification}
=42 {a universal amount of notifications}
other {# notifications}
}. Have a nice day, {name}!";
// get matches skipping nested curly braces
var matches =
Regex.Matches(str, @"{((?:[^{}]|(?<counter>{)|(?<-counter>}))+(?(counter)(?!)))}");
var results = matches.Cast<Match>().Select(m => m.Groups[1].Value).Distinct()
.Select(v => Regex.Match(v, @"^\w+").Value) // take 1st word
.ToList();
导致(在调试时从 Visual Studio Locals 窗口复制)
results Count = 2 System.Collections.Generic.List<string>
[0] "notifications"
[1] "name"
更多信息
(我只是觉得这很有趣,并花了更多时间研究/学习,并认为值得包含更多相关信息)
here 和 here 的对话中包含一些支持和反对使用正则表达式来解决此类问题的意见。
不管上述观点如何,.NET 创建者认为实现平衡组定义是合适的——这个答案使用的功能: