You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用正则表达式提取多行SAS代码的Python实现问题求助

我明白你遇到的问题了——处理单行SAS宏时正则没问题,但多行宏就抓不到内容,这其实是正则默认行为和你原来的表达式结构导致的。让我一步步帮你解决:

首先,你原来的正则里硬写了\n来分隔行,这就限制了只能匹配中间只有一行的宏。更关键的是,Python的re模块默认下,.是不匹配换行符的,所以即使你加了*或+,也没法跨多行匹配内容。这时候re.DOTALL修饰符就派上用场了,它能让.匹配包括换行在内的所有字符。

接下来,我们需要调整正则表达式,让它能灵活匹配带参数/不带参数、多行内容、以及%mend后面可能带宏名的情况(SAS允许%mend;或%mend macro_name;两种写法)。

这里给你一个可以正常工作的实现:

import re

# 示例SAS代码,包含多行宏和单行宏
sas_code = """
%macro process_data(input_ds, threshold);
    data filtered;
        set &input_ds.;
        if value > &threshold. then output;
    run;
    
    proc freq data=filtered;
        tables category;
    run;
%mend process_data;

%macro hello();
    %put Hello from simple macro!;
%mend;
"""

# 构建正则模式,使用re.DOTALL修饰符
macro_pattern = re.compile(
    r"%macro\s+(\w+)\s*(?:\((.*?)\))?\s*;(.*?)\s*%mend\s*(?:\w+)?\s*;",
    re.DOTALL
)

# 提取所有宏定义
macro_matches = macro_pattern.findall(sas_code)

# 遍历结果并打印
for macro_name, macro_params, macro_content in macro_matches:
    print(f"=== 宏名称: {macro_name} ===")
    print(f"参数: {macro_params.strip() if macro_params else '无参数'}")
    print("宏内容:")
    print(macro_content.strip())
    print("\n" + "-"*60 + "\n")

让我拆解一下这个正则的关键部分:

  • %macro\s+(\w+): 匹配%macro关键字,捕获后面的宏名称到第一个分组。
  • \s*(?:\((.*?)\))?: 匹配可选的参数列表,用非捕获组(?:...)包裹,里面的(.*?)捕获参数内容,?表示参数部分是可选的(支持无参数宏)。
  • \s*;: 匹配宏定义行末尾的分号,前后允许有空格。
  • (.*?): 非贪婪匹配宏的所有内容(包括换行),直到遇到%mend。
  • \s*%mend\s*(?:\w+)?\s*;: 匹配%mend关键字,后面可选的宏名称,最后是分号,前后允许空格。

注意事项:

  1. 非贪婪匹配.*?:一定要用非贪婪模式,否则会从第一个%macro一直匹配到最后一个%mend,把所有宏都当成一个内容。
  2. 嵌套宏的情况:如果你的SAS代码里有嵌套宏(一个宏里定义另一个宏),这个正则会失效,因为它会匹配到第一个%mend。这种复杂场景建议用专门的SAS语法解析工具,而不是正则。但大多数情况下,SAS宏不会嵌套,这个正则足够用。
  3. 空白处理:正则里的\s*可以处理代码中各种多余的空格、制表符或换行,让匹配更鲁棒。

内容的提问来源于stack exchange,提问作者Westworld

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:01:47