正则表达式跳过模式

And*_*sev 6 c# regex

问题

我需要用百分号('%')替换所有星号('*').应忽略方括号中的星号符号.

    [Test]
    public void Replace_all_asterisks_outside_the_square_brackets()
    {
        var input = "Hel[*o], w*rld!";
        var output = Regex.Replace(input, "What_pattern_should_be_there?", "%")

        Assert.AreEqual("Hel[*o], w%rld!", output));
    }
Run Code Online (Sandbox Code Playgroud)

Kob*_*obi 3

尝试使用前瞻:

\*(?![^\[\]]*\])
Run Code Online (Sandbox Code Playgroud)

这是一个更强大的解决方案,它可以更好地处理[]块,甚至转义\[字符:

string text = @"h*H\[el[*o], w*rl\]d!";
string pattern = @"
\\.                 # Match an escaped character. (to skip over it)
|
\[                  # Match a character class 
    (?:\\.|[^\]])*  # which may also contain escaped characters (to skip over it)
\]
|
(?<Asterisk>\*)     # Match `*` and add it to a group.
";

text = Regex.Replace(text, pattern,
    match => match.Groups["Asterisk"].Success ? "%" : match.Value,
    RegexOptions.IgnorePatternWhitespace);
Run Code Online (Sandbox Code Playgroud)

如果您不关心转义字符,您可以将其简化为:

\[          # Skip a character class
    [^\]]*  # until the first ']'
\]
|
(?<Asterisk>\*)
Run Code Online (Sandbox Code Playgroud)

没有注释可以写成:@"\[[^\]]*\]|(?<Asterisk>\*)"

要理解它的工作原理,我们需要了解 Regex.Replace 的工作原理:对于字符串中的每个位置,它都会尝试匹配正则表达式。如果失败,则移动一个角色。如果成功,它将在整场比赛中移动。
在这里,我们对[...]块进行了虚拟匹配,因此我们可以跳过不想替换的星号,而只匹配那些单独的星号。Asterisk该决定是在检查是否匹配的回调函数中做出的。