正则表达式简化 - 组太多
Posted
技术标签:
【中文标题】正则表达式简化 - 组太多【英文标题】:Regular expression simplification - too many groups 【发布时间】:2011-07-31 22:37:15 【问题描述】:我正在为 C 风格的预处理器编写一个简单的文本抓取器。输入文本(示例):
#if 1 > 0
blah
#if defined MACRO1
blah blah blah
#if !defined MACRO2
blaaaah
#if ! defined MACRO3
blah?
我想捕获每个 #if [!] defined
语句之后的文本。从上面的文本中我需要的输出是:
MACRO1
MACRO2
MACRO3
此处需要捕获的行号是 3、5 和 7。请注意,第 7 行包含空格和制表符。
我尝试创建可以给我这个结果的表达式,但没有一个如此出色。我给出预期结果的表达式是-
(?<=(?<=(?<=(?<=(?<=(?<=#if)[\s\t]+)!?)[\s\t]*)defined)[\s\t]+).*
使用的选项是:Multiline + IgnoreCase
但我确信这并不优雅和简洁。 谁能推荐更好的表达方式?
PS - 我正在使用Expresso 来测试表达式。
【问题讨论】:
这是另一种选择(感谢 Wessel):(?<=#if[\s\t]+[!]?[\s\t]*defined[\s\t]+).*
【参考方案1】:
这应该可以 鉴于 s 在您的问题中包含换行符等的输入
foreach(var match in Regex.Matches(s, @"(?<=#if\s*!?\s*defined\s*)(?<macro_name>\w+)"))
Console.WriteLine(match);
将找到 MACRO01、MACRO02 和 MACRO03 作为 3 个捕获
【讨论】:
确实如此!但是请帮助我理解 \s 如何在您的答案中处理选项卡?!! 很高兴它有帮助! \s* 匹配任何空格,包括制表符,* 表示 0 到多个 谢谢!我修改这些书已经好几年了。 :) 是的,\s 也处理 \t。我忘了。该死! =) 谢谢! 我使用的是普通的答案:(?<=#if\s+!?\s*defined\s+)\w+
。【参考方案2】:
这个正则表达式呢?
#if[\s\t]+[!]?[\s\t]*defined[\s\t]*(.*)
在反向引用中,你会得到 MACRO1/MACRO2/MACRO3。
【讨论】:
捕获的文本包含整行,而不是defined
word 之后的文本。
但是,哎呀,韦塞尔!!你很亲密。这有效:(?<=#if[\s\t]+[!]?[\s\t]*defined[\s\t]+).*
我不知道我在 2 小时前尝试了类似的答案。它没有用!啊!我需要咖啡。【参考方案3】:
艾娜扬
我知道您需要获取通用 c 源代码文本流中所有“#if defined”和“#if !defined”预处理器指令的宏引用名称...
我可以向你推荐那个简单的正则表达式
^#if\s*!?\s*defined\s*(\w*).*$
之前的正则表达式只定义了一个捕获组 (\w*),以便仅获取宏名称。
捕获组将被所有出现的宏名称填充。
*PS:正则表达式必须使用多行+忽略大小写选项执行。我用 RegExr 工具 http://gskinner.com/blog/archives/2008/03/regexr_free_onl.html*
测试了那个【讨论】:
捕获的文本包含整行,而不是defined
单词之后的文本。因此,这需要改进。
@Nayan:匹配的文本是整行。但是第一个也是唯一组的内容是您要提取的文本。你真的需要一个超级复杂的,这样你就不必额外调用来从匹配组中获取值吗?【参考方案4】:
这行得通吗,
^#if(?:[ \t]*!)?[ \t]*defined[ \t]*(.*?)$
没有多行选项?
【讨论】:
Marcello 提出了类似的答案。但它并没有给我确切的结果。请自行测试。以上是关于正则表达式简化 - 组太多的主要内容,如果未能解决你的问题,请参考以下文章