获取所有迭代的捕获组

时间:2015-12-02 08:46:08

标签: c# regex

我正在研究C#Regex。

输入文字:

headera
aa1aaa
aa2aaa
aa3aaa

headerb
aa4aaa
aa5aaa
aa6aaa

headerc
aa7aaa
aa8aaa
aa9aaa

我想仅捕获 headerb headerc 之间的数字4,5和6

我的尝试:

我能够用下面的图案捕捉headera和headerb下面的那些。我不能在lookbehind上应用相同的概念,因为这应该是零宽度,因此不允许量词。

aa(\d+)aaa(?=[\s|\S]*headerc)

重复捕获组只会捕获最后一次迭代。我不能为多个实例应用一些外卡正则表达式。

请协助。 感谢

[解决] 利用.Net能够支持可变宽度后视的优势。 您可以使用以下模式:

@"(?<=headerb[\s|\S]*)aa(\d)aaa(?=[\s\S]*headerc)"
@"(?s)(?<=\bheaderb\b.*?)\d+(?=.*?\bheaderc\b)"
@"(?<=\bheaderb\b(?:(?!\bheaderc\b)[\s\S])*)aa(\d+)aaa"

4 个答案:

答案 0 :(得分:4)

C#支持变量lookbehind.So使用它。

(?<=\bheaderb\b(?:(?!\bheaderc\b)[\s\S])*)aa(\d+)aaa

See Demo.

答案 1 :(得分:2)

你的正则表达式与你需要的不匹配,因为它不包括边界。注意aa(\d+)aaa(?=[\s|\S]*headerc)匹配aa,后跟一个或多个后跟任何字符的数字([\s\S][\s|\S]相同),0次或更多次出现,后跟{ {1}}。因此,您没有前导边界。

如果你坚持使用正则表达式,你可以在.NET正则表达式中使用可变宽度 lookbehind:

headerc

demo(?s)(?<=\bheaderb\b(?>(?!\bheader[bc]\b).)*)\d+ lookbehind确保在数字序列之前有一整个单词(?<=\bheaderb\b(?>(?!\bheader[bc]\b).)*)headerb以及一些0或更多字符(请注意我添加的单行修改器以强制使用headerc匹配换行符)。 .tempered greedy token,它匹配任何不包含(?>(?!\bheader[bc]\b).)*headerc整个单词的子字符串。如果在headerb之后还有另一个headerb....headerc块,则有必要(参见我的正则表达式演示)。

然而,正则表达式解决方案效率不高(尽管可能是快速而肮脏的&#34;一次性解决方案)。您还可以使用此技巧:使用换行符号将输入拆分为&#34;行&#34;列表,使用LINQ找到所需的块,然后应用简单的正则表达式查找所有数字序列:

headerc...headerd

enter image description here

答案 2 :(得分:1)

我真的建议在预先选择正确的行之后,在这种情况下简化问题并仅对每行处理使用正则表达式。

无论如何,对于这个特殊的例子,简单如下:

pip install virtualenv

应该有效。您可能需要调整空格/换行符。只需从(\ d +)组中获取数字即可。 附:为方便起见,你可以使用命名组,例如 virtualenv -p python3 envname将创建headerb\n(aa(\d+)aaa\n)+\nheaderc 组。

更多信息:https://msdn.microsoft.com/en-us/library/bs2twtah(v=vs.110).aspx

答案 3 :(得分:1)

那个正则表达式怎么样:

(?<=headerb)[\r\n]*(?:aa(?<number>\d+)aaa[\r\n]*)+(?=headerc)

Code sample

它打印出你想要的东西(4,5,6)。

var regex = new Regex(@"(?<=headerb)[\r\n]*(?:aa(?<number>\d+)aaa[\r\n]*)+(?=headerc)", RegexOptions.Singleline);
var match = regex.Match(<input>);
if (match.Success)
{
    foreach (var number in match.Groups["number"].Captures.Cast<Capture>())
    {
        Console.WriteLine(number);
    }
}