从两行获取字符串的正则表达式模式

Posted

技术标签:

【中文标题】从两行获取字符串的正则表达式模式【英文标题】:Regex Pattern that gets string from two line 【发布时间】:2021-12-03 15:44:00 【问题描述】:

我已经创建并测试了这个 Regexpattern <\w\w:Value> SYMBOL: (P.*)=(.*)\/\/(.*)

 Regex regexPattern = new Regex(@"<\w\w:Value> SYMBOL: (P.*)=(.*)\/\/(.*)");
 var attributeChecker = regexPattern.Match(line);
 var attributeLongDescription = attributeChecker.Groups[3].ToString().Trim();

这是模型:

<AC:Value> SYMBOL: PDWFNA     = 0;        // Projektierung D-Weg Freimeldung nicht
                                          // auswerten
<AC:Value> SYMBOL: PDWLE      = 0;        // Länge des Durchrutschweges

我从第三组得到的结果是:

Projektierung D-Weg Freimeldung nicht
Länge des Durchrutschweges

如何从第三组获得这些结果:

Projektierung D-Weg Freimeldung nicht auswerten
Länge des Durchrutschweges

【问题讨论】:

您不能这样做,您需要匹配模式匹配下方所有作为注释延续的行,然后对结果进行后处理。 @WiktorStribiżew 你能给我举个例子吗,我该怎么做? 我正在编写代码,但您已经得到了答案。 @WiktorStribiżew 如果你有更好的答案,你可以发布你的,我会删除我的。 @AdrianHHH 现在,问题是 1)不同,2)不清楚,因为没有输入文本,没有样本来测试模式。 kn1ghtx,请保持问题原样,如果当前解决方案只有一点问题,请在答案下方发表评论,如果问题更大,请考虑提出新问题。暂时回滚到最新的正常问题。 【参考方案1】:

您不能将字符串的不相交部分捕获到单个捕获组中。您需要匹配模式匹配下方所有作为注释延续的行,然后对结果进行后处理。

您可以使用以下方法(参见C# demo):

var text = @"<AC:Value> SYMBOL: PDWFNA     = 0;        // Projektierung D-Weg Freimeldung nicht
                                          // auswerten
<AC:Value> SYMBOL: PDWLE      = 0;        // Länge des Durchrutschweges";
var matches = Regex.Matches(text, @"<\w2:Value> SYMBOL: (P.*)=(.*)//(.*(?:\n[\s-[\r\n]]*//.*)*)");
foreach (Match m in matches) 

    Console.WriteLine("--- A new match ---");
    Console.WriteLine($"Group 1: m.Groups[1].Value");
    Console.WriteLine($"Group 2: m.Groups[2].Value");
    Console.WriteLine("Group 3: 0",
        string.Join(" ", 
            m.Groups[3].Value.Split(new[] "//", StringSplitOptions.RemoveEmptyEntries)
                .Select(x => x.Trim())
        )
    );

输出:

--- A new match ---
Group 1: PDWFNA     
Group 2:  0;        
Group 3: Projektierung D-Weg Freimeldung nicht auswerten
--- A new match ---
Group 1: PDWLE      
Group 2:  0;        
Group 3: Länge des Durchrutschweges

另请参阅regex demo。

(.*(?:\n[\s-[\r\n]]*//.*)*) 部分使用.* 将当前行的其余部分捕获到第 3 组,然后是任何零个或多个可以以 CR 和 LF 以外的零个或多个空格开头的行,然后是 //,然后直到行尾的任何内容。

string.Join(" ", m.Groups[3].Value.Split(new[] "//", StringSplitOptions.RemoveEmptyEntries).Select(x =&gt; x.Trim())) 是对第 3 组值进行后处理的一种方式。在这里,它被// 子字符串分割,然后所有生成的项目都从前导/尾随空格中删除,然后将它们连接成一个带有空格的字符串。

您也可以使用Regex.Replace(m.Groups[3].Value, @"\s*//\s*", " ") 来缩短它。

【讨论】:

仅供参考:如果注释行之间可以包含空白行,请将 [\s-[\r\n]] 替换为 \s 很好,[\s-[\r\n]][\pZs\t] 一样吗? @Thefourthbird [\s-[\r\n]] 更等于 [^\S\r\n][\pZs\t] 更具体。 @kn1ghtx 你可能想排除后面有aterisks的cmets,试试&lt;\w2:Value&gt; SYMBOL: (P.*)=(.*)//(?!\s*\*)(.*(?:\n[\s-[\r\n]]*//(?!\s*\*).*)*) @kn1ghtx 当然不是。正则表达式模式中的\n 需要找到一个LF char,当你逐行读取时,输入中没有LF。【参考方案2】:

匹配后可以处理第3组的匹配,去掉前导换行符、空格和//

<\w\w:Value> SYMBOL: (P[^=\n]*)=(.*?)//(.*(?:\n[\pZs\t]*//.*)*)

模式匹配:

&lt;\w\w:Value&gt; SYMBOL: 字面匹配 (P[^=\n]*) 捕获组 1,匹配 P 后跟不是 = 或换行符 = 字面匹配 (.*?) 捕获组 2,匹配除换行符以外的任何字符,非贪婪 // 字面上匹配 ( 捕获第 3 组 .* 匹配该行的其余部分 (?:非捕获组 \n[\pZs\t]*//.* 匹配换行符、可选空格和 // 以及该行的其余部分 )*关闭 )关闭第三组

.NET regex demo | C# demo

例如,替换后只打印第 3 组:

string pattern = @"<\w\w:Value> SYMBOL: (P[^=\n]*)=(.*?)//(.*(?:\n[\pZs\t]*//.*)*)";
string input = @"<AC:Value> SYMBOL: PDWFNA     = 0;        // Projektierung D-Weg Freimeldung nicht
                                            // auswerten
    <AC:Value> SYMBOL: PDWLE      = 0;        // Länge des Durchrutschweges"; 
        
            
foreach (Match match in Regex.Matches(input, pattern))

    Console.WriteLine(Regex.Replace(match.Groups[3].Value, @"\r?\n[\pZs\t]+//",""));              

输出

Projektierung D-Weg Freimeldung nicht auswerten
Länge des Durchrutschweges

【讨论】:

\r? 是不必要的,. 已经匹配 CR 符号。 //也可以从行首开始。 谢谢,但是我得到的是// Projektierung D-Weg Freimeldung nicht // auswerten而不是Projektierung D-Weg Freimeldung nicht auswerten

以上是关于从两行获取字符串的正则表达式模式的主要内容,如果未能解决你的问题,请参考以下文章

如何编写正则表达式模式来获取匹配的字符串?

使用正则表达式获取字符串中模式的索引

正则表达式检查上一行

正则表达式匹配在任意位置连字符并分成两行的特定单词

用于获取仅包含模式列表中单词的字符串的正则表达式?

订购一组正则表达式模式或获取最大的正则表达式匹配