我试图将两个字符串之间的行提取为单独的匹配项:
START-OF-FIELDS
Line A
Line B
Line C
END-OF-FIELDS
这是我的正则表达式:
(?<=START-OF-FIELDS)(.*\n)*(?=END-OF-FIELDS)
结果只是包含所有三行的一个匹配。我如何获得三场比赛:
答案 0 :(得分:1)
使用.net,您可以在全球研究中使用此模式:
使用多行选项:
@"(?:\G(?!\A)|START-OF-FIELDS)\r?\n(.*)(?>\r?\nEND-OF-FIELD(?=S\r?$))?"
结果在捕获组1中。
该模式适用于2个入口点。第一个是“START-OF-FIELDS”,用于第一个结果。第二个是\G(?!\A)
,用于其他结果。
\G
是最后一次匹配后字符串中位置的锚点。在开头\G
被初始化为字符串位置的开头,为了避免这种特殊情况,我添加了(?!\A)
以确保该分支在第一个位置失败。
\G
只有在第一个结果后才允许连续匹配。
为了打破连续性,我添加了一个可选的非捕获组,它匹配“END-OF-FIELDS”但没有最后一个字符。
使用C#可以实现另一种方式,因为可以提取已经重复捕获组匹配的所有内容:
使用这种模式:
string pattern = @"START-OF-FIELDS\r?\n(?>(.*)\r?\n)*?(?>END-OF-FIELD(?=S\r?$))";
Match match = Regex.Match(input, pattern, RegexOptions.Multiline);
if (match.Success) {
foreach (Capture capture in match.Groups[1].Captures) {
Console.WriteLine(capture.Value);
}
}
这种方式的优点是在找到字段时搜索停止。
答案 1 :(得分:1)
我会使用否定前瞻
^(?!START\-OF\-FIELDS|END\-OF\-FIELDS)(.*)$
您还需要m
和g
修饰符(多行和全局)
在这里演示http://regex101.com/r/xC7qJ2/2
编辑:
修正案:我还有START-OF-FIELDS之前的文本以及END-OF-FIELDS之后的文本。在这种情况下,我会得到太多的比赛。匹配必须在这两个字符串之间!
啊够公平。在这种情况下,为了完整起见,我个人只是使用类似(:?START\-OF\-FIELDS)\n(.*)\n(:?END\-OF\-FIELDS)
的模式和修饰符mgs
,然后在代码中拆分代码中换行符上的单个捕获。
答案 2 :(得分:0)
你的问题的答案是“不”。
这就是原因。
你提供的正则表达式是:
(?<=START-OF-FIELDS)(.*\n)*(?=END-OF-FIELDS)
请注意,此处有三个括号内的子表达式。其中两个是外观,但在外观之间是 一个括号内的子表达式 。
我相信您的(.*\n)*
与第一个换行符相匹配,将其放入 $ 1 (或 \\ 1 或其他)。然后尾随*
允许重复括号中的子表达式,它们永远不会被放入返回值,因为它们不是初始括号内子表达式的一部分。如果您还没有第一个括号内的子表达式,那么您将无法重复。后续重复不会作为结果返回,因为它们不在自己的括号内。
我认为有两种解决方法。
第一种方法是将整个匹配的文本放入一个单独的字符串中,例如:
(?<=START-OF-FIELDS)((.*\n)*)(?=END-OF-FIELDS)
现在您已经在 $ 1 中获得了重复的文字,并且您可以按换行符进行拆分。
第二种方式只有在你知道你只有三行时才有效。那将是:
(?<=START-OF-FIELDS)(.*\n)(.*\n)(.*\n)(?=END-OF-FIELDS)
现在你有多个子表达式,每行一个。
这些都没有完全符合你的要求,因此我最初的答案是“不”。 : - )