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"
...原始答案如下...
关于原始问题中的当前解决方案需要注意的一件事:
- 的使用
.
不匹配换行符,所以这就是它当前匹配嵌套值的原因之一(请参阅此来源)
如果我理解你的目标,这篇文章是对相关问题和解决方案的一个很好的解释和演示:
(这篇文章解决了原始问题中提到的主要挑战——嵌套花括号)
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 语句重复上面的片段以显示完整的解决方案)
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"
更多信息
(我只是觉得这很有趣,并花了更多时间研究/学习,并认为值得包含更多相关信息)
此处和此处的对话包括一些支持和反对使用正则表达式来解决此类问题的意见。
无论上述观点如何,.NET 创建者都认为实现平衡组定义是合适的——这个答案使用的功能: