正则表达式简化 - 组太多

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。我忘了。该死! =) 谢谢! 我使用的是普通的答案:(?&lt;=#if\s+!?\s*defined\s+)\w+【参考方案2】:

这个正则表达式呢?

#if[\s\t]+[!]?[\s\t]*defined[\s\t]*(.*)

在反向引用中,你会得到 MACRO1/MACRO2/MACRO3。

【讨论】:

捕获的文本包含整行,而不是defined word 之后的文本。 但是,哎呀,韦塞尔!!你很亲密。这有效:(?&lt;=#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 提出了类似的答案。但它并没有给我确切的结果。请自行测试。

以上是关于正则表达式简化 - 组太多的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法可以简化这个正则表达式?

正则表达式抓取太多文本

如何在 Hive 中使用正则表达式简化 g-mail 地址

简化 java 正则表达式代码以验证密码

[Java] 简化正则表达式的使用

我的正则表达式匹配太多。我如何让它停止? [复制]