首页 > 解决方案 > 正则表达式积极前瞻没有按我的预期工作

问题描述

我正在尝试替换字符串的某些值。这是一个示例字符串:

_-[$kr-123] * #,##0.00_-;-[$USD-456] * #,##0.00_-;_-[$GBP-789] * \";-\";??_-;_-@_-

具体来说,我想用在运行时从 a 检索到的其他字符串替换123, 456, 和- 换句话说,我认为我需要使用 a来动态替换,因为可能需要数千个不同的数字到字符串的替换.789DictionaryMatchEvaluator

我得到的最接近的正则表达式模式是:

(?:\[[^\]]*-)(?<Id>[0-9]*)(?:\])

...Id小组应该在哪里举行我的比赛。目前,此模式将匹配 eg [$kr-123][$USD-456]并且[$GBP-789]完全匹配。我的期望是,当我从非捕获组切换(?:)到正前瞻(?=)时,正则表达式将仅匹配括号之间的数字部分。显然不是。我是否误解了积极的前瞻性,或者我的正则表达式模式一开始就很差?

请注意,我确实得到了Id每个Group 的 Group Match,但我需要 theId本身,Match因为在 a 中替换 aGroup在 aMatch内不能很好地工作MatchEvaluator(或者在我看来是这样 - 尽管我并不完全熟悉 API )。

标签: c#regex

解决方案


您需要使用后视而不是第一个非捕获组,因为您正在检查的上下文位于预期匹配的左侧。

(?<=\[[^]]*-)[0-9]+(?=])

请参阅正则表达式演示。请注意,您不需要转义]字符,因为它是[^]]否定字符类中的第一个字符,并且它在(?=]). 我建议添加[到后向否定字符类中:(?<=\[[^][]*-)[0-9]+(?=]),只是为了安全起见并避免[...]内部没有数字的子字符串之间的任何过度匹配。

示例代码:

var dict = new Dictionary<string, string>(){ {"123", "word1"}, {"456", "word2"} };
var result = Regex.Replace(text, @"(?<=\[[^]]*-)[0-9]+(?=])", m => 
    dict.ContainsKey(m.Value) ? dict[m.Value] : m.Value));

推荐阅读