2011-04-02 25 views
0

我有一个具有多个正则表达式组的字符串,以及不在组中的字符串的某些部分。我需要替换一个字符,在这种情况下,只能在组内使用^,而不能在字符串中不在正则表达式组中的部分替换。C#正则表达式

这里的输入字符串:

STARTDONTREPLACEME^ENDDONTREPLACEME~STARTREPLACEME^ENDREPLACEME~STARTREPLACEME^BLAH^ENDREPLACEME~STARTDONTREPLACEME^BLAH^ENDDONTREPLACEME~

下面是输出字符串应该是什么样子:

STARTDONTREPLACEME^ENDDONTREPLACEME~STARTREPLACEMEENDREPLACEME~STARTREPLACEMEBLAHENDREPLACEME~STARTDONTREPLACEME^BLAH^ENDDONTREPLACEME~

我需要用C#来做到这一点,可以使用正则表达式。

我可以将字符串匹配成那些应该也应该不被替换的字符串,但是我在如何返回最终输出字符串方面挣扎。

+6

四月傻瓜?................... – 2011-04-02 01:35:51

+1

nope,看起来很容易,但这是一个真正的头部划痕。 – 2011-04-02 01:53:55

+0

海报也不会出现在其他人身上。还是仅仅是我? – 2011-04-02 04:23:51

回答

0

如果您能够分成应该被替换的组和不应该替换的组,那么您应该能够使用MatchEvaluator(一个接受匹配并返回一个匹配字符串)来决定当前正在处理的情况并单独返回该组的替换字符串。

您也可以在MatchEvaluator中使用额外的正则表达式。该解决方案产生预期的输出:

Regex outer = new Regex(@"STARTREPLACEME.+ENDREPLACEME", RegexOptions.Compiled); 
Regex inner = new Regex(@"\^", RegexOptions.Compiled); 

string replaced = outer.Replace(start, m => 
{ 
    return inner.Replace(m.Value, String.Empty); 
}); 
+0

你是否总是使用'Compiled'选项?这不是一个好主意。看看这个:http://blogs.msdn.com/b/bclteam/archive/2006/10/19/regex-class-caching-changes-between-net-framework-1-1-and-net-framework- 2-0-josh-free.aspx – 2011-04-02 10:09:27

+0

不,通常只有在创建我打算一遍又一遍地使用的静态正则表达式实例时。在这种情况下,我只想支付一次编译成本。如果这是一次性使用,我不会。 – 2011-04-02 17:10:03

+0

你可以给我没有lambda表达式所需的代码吗?我正在使用.NET 2.0。谢谢。 – 2011-04-04 02:33:19

1

我不知道我让你使用时遇到问题到底是什么,但它并没有多久就想出了这个结果:

string strRegex = @"STARTREPLACEME(.+)ENDREPLACEME"; 
RegexOptions myRegexOptions = RegexOptions.None; 
Regex myRegex = new Regex(strRegex, myRegexOptions); 
string strTargetString = @"STARTDONTREPLACEME^ENDDONTREPLACEME~STARTREPLACEME^ENDREPLACEME~STARTREPLACEME^BLAH^ENDREPLACEME~STARTDONTREPLACEME^BLAH^ENDDONTREPLACEME~"; 
string strReplace = "STARTREPLACEMEENDREPLACEME"; 

return myRegex.Replace(strTargetString, strReplace); 

通过使用我最喜爱的在线正则表达式工具:http://regexhero.net/tester/

那有帮助吗?

+0

不完全 - 此解决方案将删除应保留的“^ BLAH ^”之间的“BLAH”。只应删除^字符。 – 2011-04-02 04:01:39

+0

好眼睛 - 我错过了那种模式。 – holtavolt 2011-04-02 04:10:22

+0

是的。它删除〜STARTREPLACEME^BLAH^ENDREPLACEME〜,它不应该这样做。 – 2011-04-04 01:07:48

1
Regex rgx = new Regex(
    @"\^(?=(?>(?:(?!(?:START|END)(?:DONT)?REPLACEME).)*)ENDREPLACEME)"); 

string s1 = rgx.Replace(s0, String.Empty); 

说明:每一个^被发现的时候,先行提前扫描为结束符(ENDREPLACEME)。如果找到一个而没有看到任何其他分隔符,则匹配必须发生在REPLACEME组内。如果超前报告失败,则表示^在组之间或在DONTREPLACEME组内发现。

因为lookahead是零宽度断言,所以只有^实际上会在成功匹配的情况下被使用。

注意,如果分隔符是总是适当的平衡和组嵌套在其他组内从未这只会工作。

+0

感谢您的回复。它效果很好。不幸的是,在试图简化我的现实世界问题的例子时,我改变了标签。对于所有STARTREPLACEME,真实世界开始标记为REF * TC **,除了REF * TC,STARTDONTREPLACEME可以是任何5个字母组合。两个组以字符〜结尾。想法? – 2011-04-04 02:53:52

+0

所以两个标签的结尾分隔符都是一样的:'〜'?这是一个很大的区别。试试这个:'(?<=(?:REF \ * TC \ * \ * | \ \ G)[^ *〜^] *)\ ^' – 2011-04-04 07:33:07