首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >regex:否定字符类中的负查找?(.NET风味)

问regex:否定字符类中的负查找?(.NET风味)
EN

Stack Overflow用户
提问于 2010-02-01 21:28:07
回答 3查看 1.6K关注 0票数 1

我要做的是:删除围绕一个特定的未转义字符的最内部的未转义方括号(\是转义)

输入:[\[x\]]\]\[[\[y\]]

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

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

简而言之,只删除特定字符周围未转义的括号集。

我尝试了(针对y):Regex.Replace(input, @"(?<!\\)\[(.*?(?<!\\)y.*?)(?<!\\)\]",@"$1",但这似乎与第一个未转义的[ (在x之前)与最后一个]相匹配。我想我可以用一个否定字符类来替换.通配符,以排除[和],但是我真正需要否定的是这些类的未转义版本,当我试图在否定式字符类中加入像(?<!\\)这样的负面外观时,我似乎什么都不匹配。

提前感谢您的时间和努力。

编辑:

为了澄清,未转义方括号的内容可以是任何内容(除了另一个未转义的方括号),只要它们包含感兴趣的未转义字符(y)。方括号的所有内容应保持不变。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-02-02 01:03:44

回头看是这份工作的错误工具。试一试:

代码语言:javascript
复制
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\[\]\\])*匹配0或更多的(1)反斜杠后面跟着任何字符,或者(2)任何不是'y‘、方括号或反斜杠的东西。如果下一个字符是'y',它就会被消耗,(?:\\.|[^\[\]\\])*将匹配所有剩余的字符,直到下一个未转义的括号。在否定式字符类中包含两个括号(以及反斜杠)确保只匹配最内部的一组未转义括号。

使用原子群也很重要--也就是说,(?>...);这样可以防止回溯,因为我们知道回溯是无用的,当正则表达式用于不包含匹配的字符串时,可能会导致严重的性能问题。

另一种方法是使用前瞻性来断言'y‘的存在,然后使用简单得多的(?>(?:\\.|[^\[\]\\])*)来使用括号之间的字符。问题是,您现在正在对字符串进行两次传递,而要确保向前看不太远,或者不够远,这是很棘手的。通过一次完成所有的工作,可以更容易地跟踪匹配过程的每个阶段。

票数 2
EN

Stack Overflow用户

发布于 2010-02-01 22:09:29

为这个问题编写正则表达式可能过于复杂。虽然这个函数有点长,但它在概念上很简单,而且很有用:

代码语言:javascript
复制
    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;
    }
票数 2
EN

Stack Overflow用户

发布于 2010-02-01 21:48:43

问题编辑后的编辑

代码语言:javascript
复制
Regex.Replace(input, @"((?<!\\)\[(?=((\\\[)|[^[])*((?<!\\)y)))|((?<=[^\\]y((\\\]|[^]]))*)(?<!\\)\])","");

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

代码语言:javascript
复制
(?<!\\)\[ - 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
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2180217

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档