自定义正则表达式替换模式

本文关键字:模式 替换 正则表达式 自定义 | 更新日期: 2023-09-27 18:01:58

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

<>之前我不感兴趣的"一些字符串与"!2 .不感兴趣的"一些字符串";"commentar"3 .无趣;"无字符串可替换"之前

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

不包含第一个和最后一个引号的结果。

<>之前1"一些字符串与"!2"一些字符串"3不匹配之前

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

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

编辑
(?<=^[^;]*?'")(.*)(?='".*?$)

这个正则表达式将查找第一个和最后一个引号之间的所有字符串,除非前面有分号。但是我是怎么找到分号的呢?

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

搭配
'some text'

自定义正则表达式替换模式

假设

匹配定义为一个序列:

  • 从输入字符串中的第一个"开始。我们称其为第一个"或开头"
  • 打开"前无;
  • ;在序列中是允许的,如果序列中最后一个"是奇数,从第一个"开始计数。
  • ;不允许出现在序列中,如果序列中最后一个"是偶数,从第一个"开始计数。
  • 以满足上述条件的最远的"结束。

解决方案

查找第一个匹配的正则表达式(原始形式):

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

在c#中:

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

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

解释

语法的解释:

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

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

<>之前^[^;"]*"((?:"[^";]*(?="[^"]*$)|"[^";]*"|[^"]*)+)"之前

由于要求"一行的第一个和最后一个报价",每行最多有一个匹配。

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

这是带引号的字符串部分,为了便于解释而分开:

<>之前"((?:"[^";]*(?="[^"]*$)|"^";]*"|[^ "] *)+)"之前

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

<>之前"[^";]*(?="[^"]*$)"^";]*"[^ "] *之前

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

  • [^"]*:最后的报价确保是奇数报价,所以我们可以有任何包括;,但"除外。
  • "[^";]*":最后一个报价是奇数报价,后面也是奇数报价。这部分处理偶数引号后面的部分,其中不允许使用;
  • "[^";]*(?="[^"]*$):这是棘手的部分,它处理字符串有奇数引号(>= 3)的情况。我确保在偶数引号之后,没有;,然后是字符串中的最后一个引号""后跟字符串"中的最后一个引号" "是通过预先查找(?="[^"]*$)实现的。

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

试一试:

        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();

这个正则表达式可以解释为:接受以引号开始的文本,但前面没有分号,后面没有模式分号-空格-引号,并以引号结束