问题
我需要用百分号('%')替换所有星号('*')。方括号中的星号符号应该被忽略。
示例
[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));
}
答案 0 :(得分:3)
尝试使用前瞻:
\*(?![^\[\]]*\])
这是一个更强大的解决方案,可以更好地处理[]
块,甚至可以转义\[
个字符:
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);
如果您不关心转义字符,可以将其简化为:
\[ # Skip a character class
[^\]]* # until the first ']'
\]
|
(?<Asterisk>\*)
可以在没有评论的情况下编写:@"\[[^\]]*\]|(?<Asterisk>\*)"
。
要理解它的工作原理,我们需要了解Regex.Replace的工作原理:对于字符串中的每个位置,它都会尝试匹配正则表达式。如果失败,则移动一个字符。如果成功,则移动整个比赛。
在这里,我们有[...]
块的虚拟匹配,所以我们可以跳过我们不想替换的星号,并且只匹配孤独的星号。该决定是在回调函数中进行的,该函数检查Asterisk
是否匹配。
答案 1 :(得分:2)
我无法想出一个纯粹的RegEx解决方案。因此,我正在为您提供务实的解决方案。我测试了它并且它有效:
[Test]
public void Replace_all_asterisks_outside_the_square_brackets()
{
var input = "H*]e*l[*o], w*rl[*d*o] [o*] [o*o].";
var actual = ReplaceAsterisksNotInSquareBrackets(input);
var expected = "H%]e%l[*o], w%rl[*d*o] [o*] [o*o].";
Assert.AreEqual(expected, actual);
}
private static string ReplaceAsterisksNotInSquareBrackets(string s)
{
Regex rx = new Regex(@"(?<=\[[^\[\]]*)(?<asterisk>\*)(?=[^\[\]]*\])");
var matches = rx.Matches(s);
s = s.Replace('*', '%');
foreach (Match match in matches)
{
s = s.Remove(match.Groups["asterisk"].Index, 1);
s = s.Insert(match.Groups["asterisk"].Index, "*");
}
return s;
}
答案 2 :(得分:-1)
的 EDITED 强> 的
好的,这是我最后的尝试;)
使用负面后瞻(?<!)
和否定前瞻(?!)
。
var output = Regex.Replace(input, @"(?<!\[)\*(?!\])", "%");
这也将评论中的测试传递给另一个答案"Hel*o], w*rld!"