使用.NET正则表达式替换字符串中的文本

8
我需要执行两个规则的“替换”操作--我的规则是,将所有开放括号“(”替换为连字符“ - ”并删除所有关闭括号“)”。

例如:

"foobar(baz2)" 将变成

"foobar-baz2"

目前我是这样做的--但是,我有一种直觉,认为正则表达式会更简洁。

myString.Replace("(", "-").Replace(")", "");

非常感谢大家,我真的很高兴我的最初直觉是正确的。 - rsturim
8个回答

7

我不建议使用正则表达式来解决这个问题——你的方法是正确而清晰的……使用正则表达式可能不会让问题更简单或更清晰。因为对于每种情况,你仍需要调用两次Replace函数进行替换。


只需要一个调用(请参考我的示例)。然而,在这种情况下,定期更换是最好的选择。 - Ahmad Mageed

4

您可以使用一个正则表达式在一行中替换这两个出现,但它会比两个单独的规则字符串替换更不“宽容”。

例如:

要使用正则表达式执行您想要的操作的代码如下:

Regex.Replace(myString, @"([^\(]*?)\(([^\)]*?)\)", "$1-$2");

这对于您提供的确切示例可以正常工作。 如果有任何关于'('和')'字符在哪里以及数量方面的最微小更改,则正则表达式将无法正常工作。 您可以使用更多的正则表达式来修复这个问题,但它只会变得越来越丑陋。
然而,对于那些更加严格的应用程序,正则表达式是一个很棒的选择。

3
我突然想起了Jamie Zawinski的一句话:

有些人在面对问题时,会想:“我知道,我来用正则表达式。”现在他们有两个问题了。

所以我认为在这种情况下,LBushkin是正确的。你的解决方案可行且易于理解。

1

我认为对于这种情况,正则表达式可能会变得脆弱。如果您的 .NET 版本具有扩展方法,并且希望使用更清晰可扩展的语法,可以引入像这样的扩展方法:

public static class StringExtensions
{
    public static string ReplaceMany(this string s, Dictionary<string, string> replacements)
    {
        var sb = new StringBuilder(s);
        foreach (var replacement in replacements)
        {
            sb = sb.Replace(replacement.Key, replacement.Value);
        }
        return sb.ToString();
    }
}

现在你已经建立了替换字典...

var replacements = new Dictionary<string, string> { {"(", "-"}, {")", ""} };

然后调用 ReplaceMany:

var result = "foobar(baz2)".ReplaceMany(replacements); // result = foobar-baz2

如果你真的想要展示你的意图,你可以将 Dictionary<string,string> 别名为 StringReplacements

//At the top
using StringReplacements = System.Collections.Generic.Dictionary<string,string>;

//In your function
var replacements = new StringReplacements() { {"(", "-"}, {")", ""} };
var result = "foobar(baz2)".ReplaceMany(replacements);

如果只需要进行两个替换,可能有些过度了,但如果你需要进行多个替换,使用这种方式会比 .Replace().Replace().Replace().Replace()... 更加简洁。


1

不是的。这是完全干净的。

关键是,你无论如何都必须有两个正则表达式,因为你的替换字符串是不同的。


在.NET中,你可以指定一个委托来评估替换字符串,但现在我们只是让它变得更加不干净。 - LorenVS
从技术上讲,是的。但正如LorenVS已经指出的那样,这只会使整个表达变得不太清晰。 - Thomas

1
我会建议使用你已经有的 - 这样更易于阅读和维护。正则表达式非常强大,但有时也非常令人困惑。对于这么简单的事情,我会说甚至不要使用正则表达式。

0

对于这样一个简单的场景,正则表达式有些过度了。你现在的做法是完美的。虽然你的问题已经得到了回答,但我想发帖说明一个正则表达式模式就足够了:

string input = "foobar(baz2)";
string pattern = "([()])";
string result = Regex.Replace(input, pattern, m => m.Value == "(" ? "-" : "");
Console.WriteLine(result);

这个想法是捕获括号并将其分组。我使用了[()],它是一个字符类,可以匹配我们需要的内容。请注意,在字符类内部,它们不需要被转义。或者模式可以是@"(\(|\))",在这种情况下需要转义。

接下来,Replace方法使用了一个MatchEvaluator,并检查捕获的值是否是开放的(。如果是,返回一个-。如果不是,根据我们有限的模式,我们知道它必须是一个关闭的),然后返回一个空字符串。


0
这是一个有趣的基于LINQ的解决方案。它可能不是最佳选择,但无论如何都很有趣:
public string SearchAndReplace(string input)
{ 
   var openParen = '(';
   var closeParen = ')';
   var hyphen = '-';
   var newChars = input
        .Where(c => c != closeParen)
        .Select(c => c == openParen ? hyphen : c);
   return new string(newChars.ToArray());
}

关于这个实现有两个有趣的注释:

  • 它不需要复杂的正则表达式,因此可以获得更好的性能和更容易的维护。
  • 与string.Replace实现不同,此方法仅分配1个字符串。

不错!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接