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

SAS技术问询:宏变量中嵌套键值对的结构化修改方案

SAS宏变量结构化修改解决方案

问题背景

我有一个存储键值对的SAS宏变量,键值对间以空格分隔。部分值本身包含以分号分隔(末尾带分号)且用双引号包裹的嵌套键值对;单值有时带双引号有时不带。需要结构化且灵活地修改该宏变量内容。

宏变量示例:

%LET connection_string = KEY1=value1 KEY2="Value2" KEY3="KEY3A=VALUE3A;KEY3B=VALUE3B;KEY3C=VALUE WITH SPACES3C;" KEY4="KEY4A=VALUE4A;KEY4B=VALUE4B;";

修改需求

  • 在KEY3中更新KEY3B=NEW_VALUE3B
  • 在KEY3中添加KEY3D=VALUE3D
  • 在KEY4中删除KEY4B=VALUE4B
  • 添加顶层键值对KEY5="VALUE5"

初始思路

  1. 将宏变量字符串拆解为数据集
  2. 若值含分号,将其内部键值对拆解为另一个数据集
  3. 根据修改需求调整数据集
  4. 重新组合数据集生成新宏变量connection_string_upd

尝试用数据步实现时,双引号和嵌套空格的处理遇到困难,现有代码无法完成拆分,以下是可行的解决方案:

解决方案代码

1. 拆分顶层键值对到数据集

通过逐字符解析识别双引号边界,避免拆分引号内的空格:

/* 拆分顶层键值对 */
data top_pairs;
    length key $50 value $1000;
    str = "&connection_string.";
    len = length(str);
    in_quote = 0;
    start = 1;
    do pos = 1 to len;
        char = substr(str, pos, 1);
        if char = '"' then in_quote = 1 - in_quote; /* 切换引号状态 */
        /* 不在引号内且遇空格,或到字符串末尾时拆分 */
        if (in_quote = 0 and char = ' ') or pos = len then do;
            item = substr(str, start, pos - start + (pos=len));
            eq_pos = index(item, '=');
            if eq_pos > 0 then do;
                key = substr(item, 1, eq_pos - 1);
                value = substr(item, eq_pos + 1);
                value = dequote(value); /* 去除值两端的双引号 */
                output;
            end;
            start = pos + 1;
        end;
    end;
    drop str len in_quote start pos char item eq_pos;
run;

2. 拆分嵌套键值对

针对包含分号的嵌套值,拆分子键值对以便修改:

/* 拆分嵌套键值对 */
data nested_pairs;
    set top_pairs;
    if index(value, ';') > 0 then do;
        do i = 1 to countw(value, ';') - 1; /* 跳过末尾分号产生的空项 */
            nested_item = scan(value, i, ';');
            eq_pos = index(nested_item, '=');
            if eq_pos > 0 then do;
                nested_key = substr(nested_item, 1, eq_pos - 1);
                nested_value = substr(nested_item, eq_pos + 1);
                output;
            end;
        end;
    end;
    keep key nested_key nested_value;
run;

3. 执行增删改操作

通过PROC SQL修改数据集:

/* 更新KEY3的KEY3B值 */
proc sql;
    update nested_pairs
    set nested_value = 'NEW_VALUE3B'
    where key = 'KEY3' and nested_key = 'KEY3B';

/* 给KEY3添加KEY3D */
insert into nested_pairs (key, nested_key, nested_value)
values ('KEY3', 'KEY3D', 'VALUE3D');

/* 删除KEY4的KEY4B */
delete from nested_pairs
where key = 'KEY4' and nested_key = 'KEY4B';
quit;

/* 添加顶层键值对KEY5 */
proc sql;
    insert into top_pairs (key, value)
    values ('KEY5', 'VALUE5');
quit;

4. 重新组合生成新宏变量

将修改后的数据集重新拼接成宏变量:

/* 重新组合嵌套值为带引号的字符串 */
proc sql;
    create table top_pairs_updated as
    select 
        key,
        case 
            when exists (select 1 from nested_pairs np where np.key = tp.key)
            then quote(catx(';', collect(nested_key || '=' || nested_value)) || ';')
            else if index(value, ' ') > 0 then quote(value) else value
        end as value
    from top_pairs tp
    group by key;
quit;

/* 组合成最终宏变量 */
proc sql noprint;
    select catx(' ', key || '=' || value) into :connection_string_upd trimmed
    from top_pairs_updated;
quit;

/* 打印验证结果 */
%put &connection_string_upd.;

关键说明

  • 用DEQUOTE去除值两端的双引号,QUOTE在需要时重新添加,确保空格和特殊字符被正确保留。
  • 逐字符解析时通过in_quote变量区分是否在引号内,避免误拆分引号内的空格。
  • 嵌套键值对拆分时,通过countw(value, ';') -1跳过末尾分号产生的空项。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 11:13:11