在我的应用程序中,我必须解析一个文件并替换一些字符串。
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'
答案 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();
这个正则表达式可以解释为:采用以引号开头的文本,但不会立即以分号开头,后面没有模式分号空白空格 - 引用并以引号结尾