使用 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.MULTILINE
和re.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 ;
例如
pattern = re.compile(r"%macro.*\r?\n((?:(?!\s*%mend).*\r?\n)+)\s*%mend ;")
print(re.findall(pattern, test_str))
我正在尝试使用 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.MULTILINE
和re.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 ;
例如
pattern = re.compile(r"%macro.*\r?\n((?:(?!\s*%mend).*\r?\n)+)\s*%mend ;")
print(re.findall(pattern, test_str))