.net 正则表达式:否定字符类中的否定查找?(.净风味)

.net 正则表达式:否定字符类中的否定查找?(.净风味),.net,regex,lookaround,.net,Regex,Lookaround,我试图做的是:删除围绕特定的、未转义字符的最里面的未转义方括号\是转义 输入:[\[x\]\]\[\[y\]] 查找y周围的括号时输出:[\[x\]\]\[\[y\] 查找x周围的括号时输出:\[x\]\[\[y\]] 简言之,仅移除特定字符周围未缩放的括号集 我为y:Regex.Replaceinput尝试了这个方法,在问题被编辑后,@?被编辑 我们希望匹配要删除的括号: (?<!\\)\[ - Match is an unescaped left bracket (?=((\\\[)|

我试图做的是:删除围绕特定的、未转义字符的最里面的未转义方括号\是转义

输入:[\[x\]\]\[\[y\]] 查找y周围的括号时输出:[\[x\]\]\[\[y\] 查找x周围的括号时输出:\[x\]\[\[y\]]

简言之,仅移除特定字符周围未缩放的括号集

我为y:Regex.Replaceinput尝试了这个方法,在问题被编辑后,@?被编辑

我们希望匹配要删除的括号:

(?<!\\)\[ - Match is an unescaped left bracket
(?=((\\\[)|[^[])*((?<!\\)y)) - Match is followed by any number of (escaped left brackets or non-left brackets) followed by an unescaped y

| - OR

(?<=[^\\]y((\\\]|[^]]))*) - Match is preceded by unescaped y followed by any number of (escaped right brackets or non-right brackets)
(?<!\\)\] - Match is an unescaped right bracket
问题编辑后再编辑

我们希望匹配要删除的括号:

(?<!\\)\[ - Match is an unescaped left bracket
(?=((\\\[)|[^[])*((?<!\\)y)) - Match is followed by any number of (escaped left brackets or non-left brackets) followed by an unescaped y

| - OR

(?<=[^\\]y((\\\]|[^]]))*) - Match is preceded by unescaped y followed by any number of (escaped right brackets or non-right brackets)
(?<!\\)\] - Match is an unescaped right bracket

为此编写正则表达式可能会过于复杂。虽然此函数有点长,但它在概念上很简单,可以实现以下目的:

    string FixString(char x, string original)
    {
        int i = 0;
        string s = original;
        while (i < s.Length)
        {
            if (s[i] == x)
            {
                bool found = false;
                for (int j = i + 1; (j < s.Length) && !found; j++)
                {
                    if ((s[j] == ']') &&
                        (s[j-1] != '\\'))
                    {
                        s = s.Remove(j, 1);
                        found = true;
                    }
                }
                if (i > 0)
                {
                    found = false;
                    for (int j = i - 1; (j >= 0) && !found; j--)
                    {
                        if ((s[j] == '[') &&
                            ( (j == 0) ||
                              (s[j - 1] != '\\') ))
                        {
                            s = s.Remove(j, 1);
                            i--;
                            found = true;
                        }
                    }
                }
            }
            i++;
        }

        return s;
    }

为此编写正则表达式可能会过于复杂。虽然此函数有点长,但它在概念上很简单,可以实现以下目的:

    string FixString(char x, string original)
    {
        int i = 0;
        string s = original;
        while (i < s.Length)
        {
            if (s[i] == x)
            {
                bool found = false;
                for (int j = i + 1; (j < s.Length) && !found; j++)
                {
                    if ((s[j] == ']') &&
                        (s[j-1] != '\\'))
                    {
                        s = s.Remove(j, 1);
                        found = true;
                    }
                }
                if (i > 0)
                {
                    found = false;
                    for (int j = i - 1; (j >= 0) && !found; j--)
                    {
                        if ((s[j] == '[') &&
                            ( (j == 0) ||
                              (s[j - 1] != '\\') ))
                        {
                            s = s.Remove(j, 1);
                            i--;
                            found = true;
                        }
                    }
                }
            }
            i++;
        }

        return s;
    }

Lookback是此作业的错误工具。请尝试以下方法:

Regex r = new Regex(
  @"\[((?>(?:[^y\[\]\\]|\\.)*)y(?>(?:[^\[\]\\]|\\.)*))\]");

string s1 = @"[\[x\]]\]\[[\[y\]]";
Console.WriteLine(s1);
Console.WriteLine(r.Replace(s1, @"%$1%"));

Console.WriteLine();

string s2 = @"[\[x\]]\]\[[1234(\[abcycba\]\y\y)]";
Console.WriteLine(s2);
Console.WriteLine(r.Replace(s2, @"%$1%"));
结果:

[\[x\]\]\[\[y\]] [\[x\]\]\[%\[y\]%

[\[x\]\]\[[1234\[abcycba\]\y\y] [\[x\]\]\[%1234\[abcycba\]\y\y%

我用%替换了方括号,而不是删除它们,以便更清楚地看到所替换的内容

?:\.[^y\[\]\]*匹配零个或多个1反斜杠后跟任何字符,或2任何不是“y”、方括号或反斜杠的字符。如果下一个字符是“y”,它将被消耗,并且?:\.[^\[\]\]*匹配所有剩余字符,直到下一个未换格括号。将两个括号与反斜杠一起包含在否定字符类中可确保只匹配最里面的未换格括号集

使用-即?>…,这也很重要;这可以防止回溯,我们知道回溯是无用的,并且当正则表达式用于不包含匹配项的字符串时,可能会导致严重的性能问题


另一种方法是使用前瞻来断言“y”的存在,然后使用更简单的?>?:\.[^\[\]\]*使用括号之间的字符。问题是,您现在要对字符串进行两次遍历,确保“向前看”不会看得太远或不够远可能会很棘手。在一次遍历中完成所有工作可以更轻松地跟踪匹配过程每个阶段的位置。

Lookbehind是此作业的错误工具。请尝试以下方法:

Regex r = new Regex(
  @"\[((?>(?:[^y\[\]\\]|\\.)*)y(?>(?:[^\[\]\\]|\\.)*))\]");

string s1 = @"[\[x\]]\]\[[\[y\]]";
Console.WriteLine(s1);
Console.WriteLine(r.Replace(s1, @"%$1%"));

Console.WriteLine();

string s2 = @"[\[x\]]\]\[[1234(\[abcycba\]\y\y)]";
Console.WriteLine(s2);
Console.WriteLine(r.Replace(s2, @"%$1%"));
结果:

[\[x\]\]\[\[y\]] [\[x\]\]\[%\[y\]%

[\[x\]\]\[[1234\[abcycba\]\y\y] [\[x\]\]\[%1234\[abcycba\]\y\y%

我用%替换了方括号,而不是删除它们,以便更清楚地看到所替换的内容

?:\.[^y\[\]\]*匹配零个或多个1反斜杠后跟任何字符,或2任何不是“y”、方括号或反斜杠的字符。如果下一个字符是“y”,它将被消耗,并且?:\.[^\[\]\]*匹配所有剩余字符,直到下一个未换格括号。将两个括号与反斜杠一起包含在否定字符类中可确保只匹配最里面的未换格括号集

使用-即?>…,这也很重要;这可以防止回溯,我们知道回溯是无用的,并且当正则表达式用于不包含匹配项的字符串时,可能会导致严重的性能问题


另一种方法是使用前瞻来断言“y”的存在,然后使用更简单的?>?:\.[^\[\]\]*使用括号之间的字符。问题是,您现在要对字符串进行两次遍历,要确保“向前看”不会看得太远,或者看得不够远,可能会很棘手。在一次遍历中完成所有工作,可以更轻松地跟踪匹配过程每个阶段的位置。

谢谢r看看这个!我有这个原因。现在是因为,未缩放括号的内容可以是除另一个未缩放括号之外的任何内容,只要它在某个地方有未缩放的x或y。因此,如果输入是[\[x\]\]\[[1234\[abcycba\]\y\y],输出应该是[\[x\]\]\]\[1234\[abcycba\]\y\y仅删除包含未缩放y的未缩放括号。我将编辑问题以澄清。可能有一些额外的括号可以删除。感谢您查看此内容!原因是我有。现在是因为未缩放括号的内容可以是除另一个未缩放括号之外的任何内容,只要它是如果输入是[\[x\]\]\[[1234\[abcycba\]\y\y],那么输出应该是[\[x\]\]\]\[1234\[abcycba\]\y\y仅删除包含未缩放y的未缩放括号。我将编辑问题以澄清。可能其中的一些额外括号可以删除。+1用于透视检查。正则表达式可能是或可能不是一些人认为的必需技能,但每个程序员
一定能像你一样解决这样的问题。但我会使用StringBuilder,并避免使用Remove或等效工具:-+1因为我通常是那个告诉人们用疯狂的正则表达式冷静的人。谢谢。透视检查+1。正则表达式可能是,也可能不是一些人所说的必需技能,但每个程序员都必须能够像您一样解决像这样的问题。但我会使用StringBuilder,并避免使用Remove或等效工具:-+1因为我通常是那个告诉人们用疯狂的正则表达式冷静的人。谢谢,哇+为了努力,为了彻底,+1-ing非正则表达式解决方案,为了促使我最终了解原子群,可以公平地说,原子群是正则表达式的| |运算符吗?。这看起来不错;明天我将运行我的单元测试并相应地接受它。谢谢。如果我要将| |与任何东西进行比较,那就是交替:在与Perl兼容的正则表达式风格(如.NET)中,交替是像| |一样的短路,而在DFA或POSIX风格中,总是检查所有的替代。原子团让我想起的是《吃豆人》中的能量球哦+为了努力,为了彻底,+1-ing非正则表达式解决方案,为了促使我最终了解原子群,可以公平地说,原子群是正则表达式的| |运算符吗?。这看起来不错;明天我将运行我的单元测试并相应地接受它。谢谢。如果我要将| |与任何东西进行比较,那就是交替:在与Perl兼容的正则表达式风格(如.NET)中,交替是像| |一样的短路,而在DFA或POSIX风格中,总是检查所有的替代。原子团让我想起的是《吃豆人》中的能量球P