定制正则表达式替换模式

时间:2013-03-04 08:32:30

标签: c# regex

在我的应用程序中,我必须解析一个文件并替换一些字符串。

1 not intressting "some string with " " !"
2 not intressting "some string" ; "commentar"
3 not intressting ;"no string to replace"

对于结果,我期望从一行的第一个到最后一个引用的整个字符串。分号后面的整个字符串将被忽略。

结果是第一个和最后一个qoutes。

1 "some string with " " !"
2 "some string"
3 no match

我的正则表达式模式适用于引号中的所有字符串,但如何实现分号选择?

(?<=^.*?\")(.*)(?=\".*?$)

修改

(?<=^[^;]*?\")(.*)(?=\".*?$)

如果引用分号,此正则表达式将查找第一个和最后一个引号之间的所有字符串。但我怎么发现分号?

not intressting "some text" ;comment "not intressting"

配衬

'some text'

2 个答案:

答案 0 :(得分:0)

假设

匹配被定义为序列:

  • 从输入字符串中的第一个"开始。我们将此称为第一个"或开头"
  • 开幕;
  • 之前没有" 如果序列中的最后一个;为奇数,则序列中允许
  • ",从第一个"开始计算。
  • 如果序列中的最后一个;是偶数,那么序列中不允许
  • ",从第一个"算起。
  • 以满足上述条件的最远"结束。

解决方案

使用此正则表达式(原始表单)找到第一个匹配:

^(?>[^;"]*)"((?>(?>"[^";]*(?="[^"]*$)|"[^";]*"|[^"]*)+))"

在C#字符串文字中:

"^(?>[^;\"]*)\"((?>(?>\"[^\";]*(?=\"[^\"]*$)|\"[^\";]*\"|[^\"]*)+))\""

结果将在第一个捕获组中。

解释

语法说明:

  • (?>pattern)是非回溯/占有性子表达式。它可以防止发动机回溯。这是一种优化形式。
  • (?=pattern)是零宽度正向前瞻。它检查前面的字符串是否符合pattern而不消耗文本。
  • |是替代。我想在这里注意的是,正则表达式引导将从左到右检查每个规则,如果找到匹配则不会考虑其他规则。这意味着订单在确定比赛时很重要。
  • 我认为你熟悉其余部分,因为它们非常基础。

为了便于解释,我将使用原始正则表达式,删除非回溯优化:

^[^;"]*"((?:"[^";]*(?="[^"]*$)|"[^";]*"|[^"]*)+)"

由于要求“一行中的第一个和最后一个引号”,每行最多匹配一个。

通过对需求进行一些分析,我们知道感兴趣部分之前的文本不应包含;(需求的一部分)或"(否则,报价不会是第一个)。因此,我们可以编写^[^;"]*来匹配字符串开头的匹配项,并将所有内容匹配到第一个引用"

这是引用的字符串部分,为便于解释而分解:

"
(
(?:
"[^";]*(?="[^"]*$)
|
"[^";]*"
|
[^"]*
)+
)
"

让我们关注这3个片段,我将从下到上开始解释:

"[^";]*(?="[^"]*$)
"[^";]*"
[^"]*

对于这里的所有情况,我们遇到的最后一个引用总是一个奇怪的引用。

  • [^"]*:最后一个引号确保为奇数引用,因此我们可以包含;,但"除外。
  • "[^";]*":最后一个引用是奇数引用,此后也是奇数引用。此部分处理偶数引用后的部分,其中不允许;
  • "[^";]*(?="[^"]*$):这是一个棘手的部分,它处理字符串具有奇数引号(&gt; = 3)的情况。我确保在偶数引用之后,没有;并且后面跟着字符串中的最后一个引用"“后面跟着字符串”中的最后一个引用"是通过前瞻(?="[^"]*$)实现的。

片段"[^";]*(?="[^"]*$)必须放在"[^";]*"前面以避免回溯,以便我们可以应用非回溯优化。

答案 1 :(得分:0)

尝试一下:

        string[] lines = File.ReadAllLines(@"Data.txt");
        string[] lines2 = lines
            .Select(line => Regex.Match(line, @"(?<!;)""((.(?!;\s*""))*)""", RegexOptions.None).Groups[1].Value)
            .Select(line => line.Length > 0 ? line : "no match")
            .ToArray();

这个正则表达式可以解释为:采用以引号开头的文本,但不会立即以分号开头,后面没有模式分号空白空格 - 引用并以引号结尾