Python正则表达式 - 奇怪的行为 - findall与regex101不匹配

时间:2015-04-18 15:03:59

标签: python regex

(我相信问题在(?s)。*?只是顺便说一句)

我需要从文件中提取一些函数。

我有这段代码:

pattern = "^\s*[a-zA-Z_]?.*void\s+[a-zA-Z_][a-zA-Z_0-9]*\s*\((?s).*?\).*?$"
objekt = re.findall(re.compile(pattern,re.MULTILINE), string)

其中string是

extern inline void
lineBreak              (     void     )

;


extern      inline void           debugPrintf
(
const int level,
          const char        *  const                    format,
...)
{
return NULL;
}

extern void
debugPutc
(
const int level
,
const int c)
;
然而

返回

extern inline void
lineBreak              (     void     )

;


extern      inline void           debugPrintf
(
const int level,
          const char        *  const                    format,
...)
{
return NULL;
}

extern void
debugPutc
(
const int level
,
const int c)

当我在regex101上调试时,它返回我需要提取的3个函数。

regex101 demo

有谁知道问题出在哪里?谢谢。

编辑:

就在此之前,我有这种模式:

"^\s*[a-zA-Z_]?.*void\s+[a-zA-Z_][a-zA-Z_0-9]*\s*\((?:\s*?.*?\s*?)*\)\s*?$"

并且一切都运行正常,除了有灾难性的回溯并且没有为其他类型工作然后无效(如双)

2 个答案:

答案 0 :(得分:3)

它在documentation中说

  

请注意,(?x)标志会更改表达式的解析方式。它应该首先在表达式字符串中使用,或者在一个或多个空格字符之后使用。如果标志前面有非空白字符,则结果未定义。

其他旗帜似乎发生了其他奇怪的事情。在模式开始时.受到最后(?s),第二次及以后的匹配的影响。

一旦设置,Python就无法关闭标志。而且没有办法限制旗帜。 (在Perl和其他一些版本中,您可以使用作用域(?s:.*?)并禁用(?-s)

编写模式的另一种方法,就是你要寻求的效果:

pattern = r"^.*?\bvoid\s+[a-zA-Z_][a-zA-Z_0-9]*\s*\([\S\s]*?\).*$"
  • \b匹配字边界。在单词字符(A-Z,a-z,0-9和“_”)和非单词字符之间。
  • [\S\s]将匹配任何非空格或空白字符。也就是说,任何角色,包括换行符。

答案 1 :(得分:1)

你是对的,(?s)让你搞砸了。在支持内联修饰符的大多数版本中,您可以在正则表达式中的任何位置插入(?s),并且单行模式将从该点开始并保持有效直到正则表达式结束,除非您使用{{1将其关闭}}。如果它在组内,模式将在组结束时重置。或者,您可以使用模式修改组(具有嵌入模式修饰符的非捕获组):(?-s)

但Python并不是那么灵活。它不支持模式修改的组,并且内联修饰符始终会影响整个正则表达式,无论您将它放在何处。作为Markus said,解决方案是使用(?s:...)代替(JavaScript正则表达中经常使用的惯用法,它根本没有单行/ DOTALL模式)。

我还建议您对正则表达式使用Python的原始字符串表示法:

[\S\s]*?