正则表达式替换,但只在两种模式之间

时间:2009-03-03 21:33:59

标签: .net regex replace

好的,我有一个多行字符串,我正在尝试清理。

每行可能是也可能不是大块引用文本的一部分。例如:

This line is not quoted.
This part of the line is not quoted “but this is.”
This one is not quoted either.
“This entire line is quoted”
Not quoted.
“This line is quoted
and so is this one
and so is this one.”
This is not quoted “but this is
and so is this.”

我需要一个RegEx替换,它将解包硬包装的引用行,即用空格替换“\ r \ n”,但仅在引号之间。

以下是替换后应该如何看待:

This line is not quoted.
This part of the line is not quoted “but this is.”
This one is not quoted either.
“This entire line is quoted”
Not quoted.
“This line is quoted and so is this one and so is this one.”
This is not quoted “but this is and so is this.”

(注意输入文本中最后两行是多行。)

约束

  • 理想情况下需要单个Regex替换呼叫
  • 使用.NET RegEx库
  • 引号总是开始/结束的引号,而不是普通的'双勾号(“),这应该会让这更容易。

重要约束

这不是直接的.NET代码,我填充了一个“searchfor / replacewith”字符串表,然后通过RegEx.Replace调用。我没有能力添加自定义代码,如匹配评估器,循环捕获的组等等。

目前的答案到目前为止,还有以下几点:

r.Replace("(?<=“)\r\n(?=”)", " ")

显然,我还没有接近。

相同的逻辑可以应用于编程代码中的块注释的颜色编码 - 块注释中的任何内容都不会与注释之外的内容一样。 (代码有点棘手,因为开始/结束块注释分隔符也可以合法地存在于字符串中,这是我不必处理的问题。)

5 个答案:

答案 0 :(得分:4)

假设所有卷曲引号都是正确平衡的,那么这个正则表达式应该做你想要的:

@"[\r\n]+(?=[^“”]*”)"

[\r\n]+将匹配任何类型的一个或多个行分隔符 - Unix(\ n),DOS(\ r \ n)或旧版Mac(\ r \ n)。然后前瞻断言前面有一个关闭报价,并且这里和那里之间没有开放报价。然后你的替换文本可以是一个简单的空格字符。

答案 1 :(得分:1)

注意:为了测试正则表达式,我使用http://gskinner.com/RegExr/非常有用。

我认为您不能编写一个表达式来替换未定义数量的换行符。但是,您可以编写一个表达式来替换一个或多个,并重复运行或写入它来处理您在一个引用部分中的最大新行数。

首先,您需要单行模式,以便表达式匹配整个输入字符串而不是逐行。将它放在表达式的开头,将其打开:

(?s)

然后,您需要一个后视表达式来匹配起始引用:

(?<=“)

预测与最终报价匹配:

(?=”)

现在是一个表达式,用于匹配某些文本,然后是换行符,然后是一些文本:

([^”\r]*)\r?([^”\r]*)

请注意,换行符周围的文本位有两个捕获组,因此您可以在替换表达式中包含该文本。这将匹配引号中只有一个换行符的文本。要将其扩展为两个换行符,只需添加另一个可选换行符和可选的以下文本:

(?s)(?<=“)([^”\r]*)\r?([^”\r]*)\r?([^”\r]*)(?=”)

您可以对此进行扩展,以匹配您认为可能出现的多个换行符。不完美,但也许足够了。或者,如果您可以在文本上重复运行表达式,则只需一次替换一个表达式。

让你的表达式像这样:

r.Replace("(?s)(?<=“)([^”\r]*)\r?([^”\r]*)", "$1 $2")

(这不太正确,因为它会在文本之后添加一个空格,即使第二组不匹配......但它是一个开始)

答案 2 :(得分:0)

所以要做的是找到一个以开头引号开头的字符串,后跟一个包含结束引号或任何\ r \ n字符的字符串,后跟一个字符串一系列一个或多个\ r \ n字符,捕获除终端\ r \ n字符之外的所有字符,并将整个匹配替换为捕获的部分。

- MarkusQ

答案 3 :(得分:0)

我认为最简单的方法是将引用的部分与“(?s:.*?)”匹配,并使用MatchEvaluator删除任何换行符。 MatchEvaluator代码可以像

一样简单
Replace(@"\s+", " ");

当然,您可以对此进行优化,以仅匹配实际包含换行符的引用部分,并仅替换这些部分中的换行符而不是所有空格,但这可能不值得。

答案 4 :(得分:0)

你无法在你所描述的限度内做你想做的事。

证明:

  • 您的固定替换表将执行固定数量的调用以替换(调用此n)
  • 每次更换只能消除固定数量的换行符(将此号码称为m)。

因此

  • 无法正确处理带有m * n + 1换行符的带引号的块。

您需要增加设置的功能(例如,允许更复杂的替换,递归替换,无限重复标记或......?)或接受您的引擎无法完成此任务的事实

- MarkusQ