我正在研究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"
答案 0 :(得分:4)
答案 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
答案 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)
它打印出你想要的东西(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);
}
}