一种解析SAS程序文件中的变量的方法

        笔者使用的SAS数据库查询平台,对接了一个以JSON格式的分级授权引擎,需将用户提交给数据库查询的SQL语句拼接在JSON入参里,但大量用户使用的数据库查询语句SQL超长(超过32767字节),这里,需把超长的SQL语句保存为程序文件。一般情况下,数据库SQL查询语句使用了大量的参数变量,但分级授权引擎不接受传入变量的语法。

        如何在SASEG提交给分级授权引擎前将程序文件里的变量解析成变量值呢?笔者尝试了多种方法,终于找到了一种可行有效的方法。

        尝试一、直接变量替换法

        思路很简单,直接将变量替换为变量值。举例如下:

        简单的SQL查询语句(带变量name1)

select name,sex,age,height,weight
from sashelp.class
where name = &name1.

        SAS EG里处理程序如下:

filename file1 "C:\saswork\sasdev\EGProject\resolve_var\prog1.sas";
filename file2 "C:\saswork\sasdev\EGProject\resolve_var\prog2.sas";
%let name1='简';
data _null_;
	infile file1;
	file file2;
	input;
	length str1 $32767;
	str1=tranwrd(_infile,'&name1.',"&name1.");
	put str1;
run;

        这里,直接将程序文件中的变量&name1.,用替换函数tranwrd,替换为变量的值。但这种方法有个致命的缺陷,无法知道SQL查询语句中具体的变量名和个数。此路不通。

        尝试二、使用宏变量自动解析变量的机制

        正好使用SAS宏变量会自动解析变量的原理,将程序文件读入到SAS数据集中,然后赋值给宏变量,这样可自动解析成变量值,巧妙地规避了要知晓具体变量名的问题。

        简单测试代码如下:

options symbolgen mprint mlogic;
%let name1='简';
%let str1=%str(select name,age from sashelp.class where name = &name1.);
%put &str1;

        返回结果如下:

25         options symbolgen mprint mlogic;
26         %let name1='简';
27         %let str1=%str(select name,age from sashelp.class where name = &name1.);
SYMBOLGEN:  宏变量 NAME1 解析为 '简'
28         %put &str1;
SYMBOLGEN:  宏变量 STR1 解析为 select name,age from sashelp.class where name = '简'
SYMBOLGEN:  上一值中宏应引用的某些字符在显示时未加引用。
select name,age from sashelp.class where name = '简'

         一种有效可行的程序文件变量解析方法,呼之欲出了,经过笔者几天的奋力coding、debugging、testing。。。终于能端出来啦。

        直接上代码吧。

%macro pgm_resolve_vars;
options noquotelenmax;
filename file1 "C:\saswork\sasdev\EGProject\resolve_var\prog1.sas";
filename file2 "C:\saswork\sasdev\EGProject\resolve_var\prog2.sas";
%let name1='简';
/*读取程序文件到数据集temp1,并设置变量解析标识var_flag*/
data temp1;
	infile file1 truncover lrecl=32767;
	input;
	length str1 $32767;
	str1=_infile_;
	length var_flag $1;
	if index(str1,'&')>0 then var_flag='1';
	else var_flag='0';
run;
/*过滤空行,判断有变量解析行就设置pgm_flag为1*/
data temp2;
	set temp1(where=(lengthn(str1)>0)) end=eof;
	retain pgm_flag;
	if var_flag='1' then pgm_flag='1';
	index=_N_;
	if eof then call symputx('pgm_flag',pgm_flag);
run;
/*生成只包含需变量解析的行*/
data temp3(keep=text1 index var_idx);
	set temp2(where=(var_flag='1')) end=eof;
	rename str1=text1;
	var_idx=_N_;
	if eof then call symputx('totnum',_N_);
run;
/*循环解析变量,更新到数据集temp2中*/
%do i=1 %to &totnum;
	data _null_;
		set temp3(where=(var_idx=&i));
		call symputx("col&i",text1);
		call symputx("num&i",index);
		call symputx('dq_flag',find(text1,'"',1);/*判断是否包含双引号*/
	run;
	%if &dq_flag>0 %then %do;
		%let text2=%bquote(&&col&i.);/*使用宏函数避免读取包含双引号字符串的问题*/
		data temp2;
			set temp2;
			if index=&&num&i then str1="&text2";
		run;
	%end;
	%else %do;
		%let text2="&&col&i.";
		data temp2;
			set temp2;
			if index=&&num&i then str1=&text2;
		run;
	%end;
%end;
/*将临时表temp2中所有内容输出到程序文件file2*/
data _null_;
	file file2;
	set temp2;
	put str1;
run;
/*查看变量解析后程序文件*/
data _null_;
	infile file2;
	input;
	put _infile_;
run;

/*清理临时数据集*/
proc datasets lib=work memtype=data kill nolist;quit;

%mend;
options symbolgen mprint mlogic;
%pgm_resolve_vars

        希望对你有帮助,也非常欢迎进一步讨论学习!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值