我要做的是:删除围绕一个特定的未转义字符的最内部的未转义方括号(\是转义)
输入:[\[x\]]\]\[[\[y\]]
查找y:[\[x\]]\]\[\[y\]周围括号时的输出
当查找x:\[x\]\]\[[\[y\]]周围的括号时输出
简而言之,只删除特定字符周围未转义的括号集。
我尝试了(针对y):Regex.Replace(input, @"(?<!\\)\[(.*?(?<!\\)y.*?)(?<!\\)\]",@"$1",但这似乎与第一个未转义的[ (在x之前)与最后一个]相匹配。我想我可以用一个否定字符类来替换.通配符,以排除[和],但是我真正需要否定的是这些类的未转义版本,当我试图在否定式字符类中加入像(?<!\\)这样的负面外观时,我似乎什么都不匹配。
提前感谢您的时间和努力。
编辑:
为了澄清,未转义方括号的内容可以是任何内容(除了另一个未转义的方括号),只要它们包含感兴趣的未转义字符(y)。方括号的所有内容应保持不变。
发布于 2010-02-02 01:03:44
回头看是这份工作的错误工具。试一试:
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‘的存在,然后使用简单得多的(?>(?:\\.|[^\[\]\\])*)来使用括号之间的字符。问题是,您现在正在对字符串进行两次传递,而要确保向前看不太远,或者不够远,这是很棘手的。通过一次完成所有的工作,可以更容易地跟踪匹配过程的每个阶段。
发布于 2010-02-01 22:09:29
为这个问题编写正则表达式可能过于复杂。虽然这个函数有点长,但它在概念上很简单,而且很有用:
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;
}发布于 2010-02-01 21:48:43
问题编辑后的编辑
Regex.Replace(input, @"((?<!\\)\[(?=((\\\[)|[^[])*((?<!\\)y)))|((?<=[^\\]y((\\\]|[^]]))*)(?<!\\)\])","");我们希望与要删除的方括号相匹配:
(?<!\\)\[ - 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 brackethttps://stackoverflow.com/questions/2180217
复制相似问题