正则表达式匹配替换求解

yangyibang 2008-11-18 09:29:30
我想用正则表达式来转义单引号的问题。
若单引号前面没有\,
则在前面加反斜杠。若有多个则替换为1个反斜杠。
我的代码如下

//替换表达式
private string ReplaceQuote(string input)
{
string pattern = @"(?:\\)*(?=['])";
return Regex.Replace(input, pattern, new MatchEvaluator(ReplaceText));
}

// 匹配项
public string ReplaceText(Match m)
{
string str = m.Value;
int n = m.Index;
if (str.Length >= 1)
{
return string.Empty;
}
return @"\";
}


要替换的文本

string strInput = @"'qq''''\''\\\\\\\\\\\'dnaaaa";
string re = ReplaceQuote(strInput);


返回的是"\\'qq\\'\\'\\'\\'\\'\\'\\'dnaaaa" 想要的结果
我的理解是若只匹配到单引号,则在此单引号前插入1个反斜杠(匹配了前面的位置),匹配到多个反斜杠(匹配的多个反斜杠字符),则用1个反斜杠替换它。
其实2个不都是替换为1个反斜杠的吗。
我认为的写法是如下


public string ReplaceText(Match m)
{
return @"\";
}



但返回的是"\\'qq\\'\\'\\'\\'\\\\'\\'\\\\'dnaaaa" 不是想要的结果

请高人指点。
...全文
301 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
linjiancun 2009-10-13
  • 打赏
  • 举报
回复
好东西,顶下!~
止戈而立 2008-11-19
  • 打赏
  • 举报
回复
过客真强。。学习了。。

本来经过几番试验,也基本理解了这个原理,但是无法表述出来。。
之前下了《精通正则表达式》的电子书,还没看。。看来得好好看看才行。
-过客- 2008-11-19
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 yangyibang 的回复:]
我基本上知道了。用个简单的字符串把。 string str = @"\\'dnaaaa";

从字符串的位置0开始查找\,零位置右边有1个反斜杠符合匹配,
继续前进,又找到一个。在位置2处的右边没有符合的匹配,但右边接的是单引号。
故此次匹配组返回\\ 会在位置0处插入一个反斜杠并替换掉匹配的2个反斜杠。

接着,在位置2处右边接着0个反斜杠,且该位置右边紧接着单引号,故此位置匹配。 会在位置2处插入一个反斜杠且替换掉0个反斜…
[/Quote]

楼主的这个理解已经基本上差不多了

就以楼主举的这个例子吧

string pattern = @"(?:\\)*(?=['])";
第一轮匹配,首先从位置0开始匹配,因为(?:\\)*是贪婪匹配,所以会尽可能多的匹配,遇到第一个字符\匹配成功,接着尝试匹配第二个字符\,匹配成功,接着尝试匹配第三个字符',匹配失败,回溯,控制权交给(?=[']),因为它是零宽度的,所以它会尝试匹配位置2,匹配成功,此时整个表达式匹配成功,匹配结果是\\,也就是第一个字符和第二个字符

接下来进入第二轮匹配,此时应该从位置2开始匹配,因为(?:\\)*是贪婪匹配,所以它首先要尝试一下,尝试匹配第一个字符',匹配失败,回溯,控制权交给(?=[']),尝试匹配位置2,匹配成功,此时整个表达式匹配成功,匹配的结果就是位置2,是零宽度的

接下来进入第三轮匹配,从'后的位置开始,匹配失败,继续,一直尝试匹配到结束,都失败

能看得出来楼主看过《精通正则表达式》这本书,这是本好书,但也不要陷到这本书里
楼主的例子,如果是用来研究原理的,我不做什么评论,只能认为它并不是一个好例子
如果是用来实现这一功能的,我只能说是舍本逐末了,一个正则表达式就可以搞定的问题,却要费这么大劲。。。
止戈而立 2008-11-19
  • 打赏
  • 举报
回复
我的意思即是说\'满足string pattern = @"(?:\\)*(?=['])";的匹配,这里匹配到的字符串是\,
接着再往后匹配,就能匹配到\后的'号,这里匹配到的字符串是空串。。
所以进行替换的话,\'会被替换成\\'
止戈而立 2008-11-19
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 yangyibang 的回复:]
引用 11 楼 min_jie 的回复:
发现一个更怪异的情况:

C# codeRegex.Replace("\\abc",@"\\*","\\");


猜下结果是什么?


我没在程序中运行这段代码,我猜是在0位置插入1个反斜杠,在位置2处插入1个反斜杠,在位置3,4处也分别插入1个反斜杠,
[/Quote]

是的,这正是解释了提出的问题啊。。
说明了\\*会匹配空字符,即""
也就是说,它会在所有的位置上都替换一个\
yangyibang 2008-11-19
  • 打赏
  • 举报
回复
其实也不是什么怪异的事情,而是没有理解正则的匹配原理才怪异,
大家都跑题了,

我提的问题并不是要怎么替换比较好,而是它的匹配原理
yangyibang 2008-11-19
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 min_jie 的回复:]
发现一个更怪异的情况:

C# codeRegex.Replace("\\abc",@"\\*","\\");


猜下结果是什么?
[/Quote]

我没在程序中运行这段代码,我猜是在0位置插入1个反斜杠,在位置2处插入1个反斜杠,在位置3,4处也分别插入1个反斜杠,
止戈而立 2008-11-19
  • 打赏
  • 举报
回复
楼主的代码要是改成下面这样就正确了。。(问题出在当pattern是\\*的时候,并且跟后面是否有(?=XXX)没关系)

//替换表达式
private string ReplaceQuote(string input)
{
string pattern = @"(?:\\)*')";//这里改成string pattern = @"\\*'";也可以
return Regex.Replace(input, pattern, new MatchEvaluator(ReplaceText));
}

// 匹配项
public string ReplaceText(Match m)
{
return @"\'";
}


止戈而立 2008-11-19
  • 打赏
  • 举报
回复
发现一个更怪异的情况:
Regex.Replace("\\abc",@"\\*","\\");

猜下结果是什么?
风骑士之怒 2008-11-19
  • 打赏
  • 举报
回复
索引位置从0 1 2 ......
yangyibang 2008-11-19
  • 打赏
  • 举报
回复
精通正则表达式,看过一遍真是效果不大。还要复习复习。
Eagle_ice 2008-11-18
  • 打赏
  • 举报
回复
先留个名...
diffmaker 2008-11-18
  • 打赏
  • 举报
回复

public string ReplaceText(Match m)
{
string str = m.Value;
int n = m.Index;
if (str.Length >= 1)
{
return string.Empty;
}
return @"\";
}


上面这个
  在匹配长度大于1时,返回空串,也就是将匹配的结果替换为空
  在匹配长度为0时,返回反斜杠,也就是用反斜杠替换原来的0长度匹配

你下面的这个,则总是返回反斜杠,所以不对了

public string ReplaceText(Match m)
{
return @"\";
}
diffmaker 2008-11-18
  • 打赏
  • 举报
回复

string test = @"'qq''''\''\\\\\\\\\\\'dnaaaa";
Regex re = new Regex(@"(\\*')");
Console.WriteLine(test);
Console.WriteLine(re.Replace(test, @"\'"));
Console.ReadKey();


楼主是不是搞复杂了?我觉得挺好整的呢。
yangyibang 2008-11-18
  • 打赏
  • 举报
回复
我的意思是请高人帮我解释下我发的C#代码片段1的正则表达式的匹配替换原理。
片段1已经实现了我的要求。
yangyibang 2008-11-18
  • 打赏
  • 举报
回复
csdn真是不好用,连发个帖子,插入个图片都不能从本地上传。
yangyibang 2008-11-18
  • 打赏
  • 举报
回复
我基本上知道了。用个简单的字符串把。 string str = @"\\'dnaaaa";


从字符串的位置0开始查找\,零位置右边有1个反斜杠符合匹配,
继续前进,又找到一个。在位置2处的右边没有符合的匹配,但右边接的是单引号。
故此次匹配组返回\\ 会在位置0处插入一个反斜杠并替换掉匹配的2个反斜杠。

接着,在位置2处右边接着0个反斜杠,且该位置右边紧接着单引号,故此位置匹配。 会在位置2处插入一个反斜杠且替换掉0个反斜杠。


感觉理解的还是不是很透彻。
止戈而立 2008-11-18
  • 打赏
  • 举报
回复
([\\]+|(?<=[^\\]))'

如:
this.textBox2.Text=Regex.Replace(this.textBox2.Text,@"([\\]+|(?<=[^\\]))'","\\'");
huoxudong125 2008-11-18
  • 打赏
  • 举报
回复
帮up
好久不用有点忘了

110,539

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧