C# Regexp跳过模式

C# Regexp跳过模式,c#,regex,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?", "%")

问题

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

示例

    [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));
    }

尝试使用前瞻:

\*(?![^\[\]]*\])
这里有一个更强大的解决方案,它可以更好地处理
[]
块,甚至转义
\[
字符:

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);
string text=@“h*h\[el[*o],w*rl\]d!”;
字符串模式=@“
\\.#匹配转义字符。(跳过)
|
\[#匹配字符类
(?:\.\.[^\]])*#也可能包含转义字符(跳过它)
\]
|
(?\*)匹配`*`并将其添加到组中。
";
text=Regex.Replace(文本、模式、,
match=>match.Groups[“星号”]。成功?%“:match.Value,
RegexOptions.ignorepattern(空格);
如果您不关心转义字符,可以将其简化为:

\[          # Skip a character class
    [^\]]*  # until the first ']'
\]
|
(?<Asterisk>\*)
\[\35;跳过字符类
[^\]*#直到第一个']'
\]
|
(?\*)
可以在没有注释的情况下编写为:
@“\[[^\]*\]\\]\\]|(?\*)”

为了理解它的工作原理,我们需要了解Regex.Replace是如何工作的:对于字符串中的每个位置,它都试图匹配Regex。如果失败,则移动一个字符。如果成功,它将覆盖整个比赛。
这里,我们为
[…]
块提供了虚拟匹配,因此我们可以跳过我们不想替换的星号,只匹配单独的星号。这个决定是在一个回调函数中做出的,该函数检查星号是否匹配。

编辑

好的,这是我的最后一次尝试;)

使用负向后看
(?和负向前看
(?!)


var output=Regex.Replace(input,@)(?我无法想出一个纯粹的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;
}
[测试]
公共无效替换方括号外的所有星号()
{
var input=“H*]e*l[*o],w*rl[*d*o][o*][o*o]”;
var actual=替换星号KSNOTINSQUAREBRACKETS(输入);
var expected=“H%]e%l[*o],w%rl[*d*o][o*][o*o]”;
断言.AreEqual(预期、实际);
}
专用静态字符串替换AsterisksNotInSquareBackets(字符串s)
{

Regex rx=new Regex(@)(?-1:请阅读他的问题!你错过了真正的问题:跳过方括号中的星号sah-方括号中的星号需要忽略。我将更新我的答案。这也不起作用。请使用以下字符串检查:
H*]e*l[*o],w*rl[*d*o][o*][o*o].
这是一个相当棘手的问题……到目前为止,这是最好的答案,但下面的例子不起作用:
Hel*o],w*rld!
在本例中,第一个星号不在方括号中,因此应该被替换。但是您的正则表达式跳过了它。@Daniel-试试下一个。我稍后会解释得更好,我现在没有时间。它会过去的我的测试如下所述。很好!我甚至不打算去理解它。-)在我看来,用纯正则表达式解决这个任务也是一个大问题:很难维护。我承认,我的解决方案不是很清楚;-)@丹尼尔-我对它做了一些简化并添加了一些解释,我希望你这次至少试着理解一下
:)
与我的评论相反,我试着理解复杂的版本,但很清楚:-)+1用于在问题中编写单元测试。根据字符串的确切规则,您可能可以找到一种模式来替换星号,而无需回调(如您所问),如果您定义清晰的规则,它会更容易:您有转义字符吗?您有不匹配的方括号吗?如果有,您将如何处理不同的边缘情况?方括号块可以嵌套吗?@Koby-您的模式
@“\[^\]*\]\]|(?\*)
,回调函数足以解决我的问题。谢谢:)
[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;
}