问题
我需要用百分号('%')替换所有星号('*').应忽略方括号中的星号符号.
例
[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)
尝试使用前瞻:
\*(?![^\[\]]*\])
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该决定是在检查是否匹配的回调函数中做出的。