正则表达式替换除特定模式之外的所有内容

Regex replace everything except a particular pattern

我要提取:

50%

来自大致具有这种格式的字符串:

The 50% is in here somewhere.

我也想提取:

50%50%25%

来自这样的字符串:

50% of 50% is 25%

Regex.Match() 似乎是明显的竞争者。但是,这涉及检查是否找到任何匹配项(例如 match.Success),从数组中的特定索引中提取结果,and/or 处理越界索引的风险。

正则表达式替换通常更易于应用。一行就完成了这项工作,包括返回结果字符串。许多语言都是如此。

result = Regex.Replace(input, stuffWeDontLike, "")

基本上,我正在寻找一个 regex 过滤器 - 而不是输入模式 replace,我想输入模式以检索.

percentages = Regex.Filter("50% of 50% is 25%", "[0-9]+\%")

我们能否形成一个正则表达式并反转结果,就好像它是一个选择一样?这将允许使用正则表达式替换。但是,我找不到轻松反转正则表达式的方法。

我们如何使用类似于正则表达式替换的非常短和简单的语法来获得所需的结果(或类似的;连接左右似乎可以接受)?

一种解决方案是使用正则表达式替换如下:

Regex.Replace("50% of 50% is 25%", "(\d+\%)|(?:.+?)", "");

输出:

50%50%25%

作为一般方法:

Regex.Replace(input, (pattern)|(?:.+?), "");

这会找到与以下任一匹配的任何内容:

  • 模式。捕获为 </code>。这就是我们想要保留的。</li> <li>任意字符,任意次数,但非贪婪。这会找到任何 <em>not</em> 被第一组捕获的东西。 <code>?:因为我们不需要捕获这个组。

如 MSDN 所述:“ 用第一个捕获的子表达式替换整个匹配项。” (也就是说,连接该子字符串的所有匹配项。)

实际上,这就是所描述的 regex 过滤器

您可以使用 Regex.Matches 并连接每个匹配结果。选一个你最喜欢的吧。

//Sadly, we can't extend the Regex class
public class RegExp
{
    //usage : RegExp.Filter("50% of 50% is 25%", @"[0-9]+\%")
    public static string Filter(string input, string pattern)
    {
        return Regex.Matches(input, pattern).Cast<Match>()
            .Aggregate(string.Empty, (a,m) => a += m.Value);
    }
}

public static class StringExtension
{
    //usage : "50% of 50% is 25%".Filter(@"[0-9]+\%")
    public static string Filter(this string input, string pattern)
    {
        return Regex.Matches(input, pattern).Cast<Match>()
            .Aggregate(string.Empty, (a,m) => a += m.Value);
    }
}

我不明白你为什么要使用替换。一开始为什么要走那条路? Regex class 中有一些方法可以让您精确地获得所有想要的匹配项。我发现你解决问题的迂回方式毫无意义。

只需使用 Matches() 来收集比赛。然后您可以将它们连接到您想要的字符串中。

var str = "50% of 50% is 25%";
var re = new Regex(@"\d+%");
var ms = re.Matches(str);
var values = ms.Cast<Match>().Select(m => m.Value);
var joined = String.Join("", values); // "50%50%25%"