使用 Regex 提取多行 SAS 代码

Using Regex to extract multi-line SAS code

我正在尝试使用 Python 遍历数千行 SAS 代码。我想提取代码的某些部分进行打印或发送到另一个函数。

我正在查看的 SAS 代码可能如下所示:

"""%macro msg (name= some_macro) ;
%put Hello World, my name is &name ;
 %mend ;"""

我想捕捉第一行和最后一行之间的内容,即 %macro%mend ; 行之间的内容,所以“%put Hello World, my name is &name ;”将 return 编为一个组。

我可以通过以下方式实现捕获:

re.compile(r"\%macro\s*?.*?\s*?\((.*)\)\s*?;\n(.*?)\n\s*\%mend\s*;")

因为(.*?)\n似乎符合我想要的行。

注意:我使用了很多 \s*,因为我看到 SAS 代码中到处都是空白,这似乎是非常随机的。

然而,当 SAS 代码超过多行时(可能是 2 行或更多),我没有模式匹配的能力,例如,

"""%macro msg (name= some_macro) ;
%put Hello World, my name is &name ;
%let something happen
%do something else
%mend ;"""

在这里,我想 return“%put Hello World,我的名字是 &name ;%let something happen %do something else”全部作为一组。我试过输入量词 *+ 但我不知道如何明确要检查整行重复,而不仅仅是我把量词放在旁边的最后一个字符.我将以此为例:

r"\%macro\s*?.*?\s*?\((.*)\)\s*?;\n(.*?)\n+?\s*\%mend\s*;"

这里我试图表明行 (.*?)\n 可以在 1 到无限次之间重复,并且我想捕获该组。

我也尝试过使用re.MULTILINEre.DOTALL,使用^和$以及点号作为行尾字符,但也没有达到预期的效果。

请帮助我更好地了解这方面。谢谢

您可以使用单个捕获组并匹配不以 %mend 开头的行。

百分号不需要转义,请注意,如果不需要,\s 也可以匹配换行符。

%macro.*\r?\n((?:(?!\s*%mend).*\r?\n)+)\s*%mend ;

说明

  • %macro.*\r?\n 匹配 %macro 后跟行的其余部分和换行符
  • ( 捕获 组 1
    • (?:非捕获组
      • (?!\s*%mend) 负前瞻,如果右边的不是%mend
      • .*\r?\n匹配整行和换行
    • )+关闭非捕获组并重复1+次以匹配至少一行
  • ) 关闭捕获组 1
  • \s*%mend ;

regex demo | Python demo

例如

pattern = re.compile(r"%macro.*\r?\n((?:(?!\s*%mend).*\r?\n)+)\s*%mend ;")
print(re.findall(pattern, test_str))