使用%sysfunc调用CATT()函数时,有没有办法阻止它评估表达式?
例如给出代码:
%let date=10-13-2015;
%put %sysfunc(catt(The date Is:,&date));
我希望它返回:
The date Is:10-13-2015
因为10-13-2015只是一个文本字符串。但是,CATT()将连字符视为减法符号,并将其作为数值表达式进行计算,返回:
The date Is:-2018
我尝试过宏引用,但没有改变任何东西,我想因为我需要以某种方式隐藏来自CATT()的值。似乎CATT的任何参数看起来像一个表达式,它将被视为这样。
另一个例子:
%let value=2 and 3;
%put %sysfunc(catt(The value Is:,&value));
The value Is:1
答案 0 :(得分:1)
如果您可以这样做,只需删除逗号即可 - 无需将其分成单个参数(除非您使用的是catx()
而不是catt()
:
%let date=10-13-2015;
%put %sysfunc(catt(The date Is: &date));
就个人而言,我认为最好的工作方式是将日期存储为SAS日期值,然后使用%sysfunc
的第二个(可选)参数来应用格式。这提供了更好的灵活性。
%let date = %sysfunc(mdy(10,13,2015));
%put The date Is: %sysfunc(sum(&date),mmddyyd10.);
如果您坚持使用原始方法并且正在使用catx()
,那么我不知道该怎么做。我能得到的最接近的是插入一段文本,因此无法将其解释为表达式,然后使用tranwrd
删除该文本。漂亮,丑陋,它留下了一个空间:
%let date=10-13-2015;
%let tmp=%sysfunc(catx(#, The date Is: , UNIQUE_STRING_TO_REMOVE&date ));
%let want=%sysfunc(tranwrd(&tmp, UNIQUE_STRING_TO_REMOVE, ));
%put &want;
给出:
The date Is:# 10-13-2015
我还尝试了宏引用的每个组合,并扫描整个SAS功能列表,看不到任何其他可行的选项。
答案 1 :(得分:1)
评估参数的%SYSFUNC()问题不仅限于CAT()系列函数。任何接受数值的函数都会导致SAS尝试评估提供的表达式。
这可能是一个有用的功能。例如:
%let start_dt=10OCT2012 ;
%put %sysfunc(putn("&start_dt"d +1,date9));
您不需要使用CAT()函数来处理宏变量。只需扩展彼此相邻的值,就可以“连接”。
%let date=10-13-2015;
%put The date Is:&date;
如果你想制作一个像CATX()函数一样的宏,那么这也不难做到。
%macro catx /parmbuff ;
%local dlm return i ;
%if %length(&syspbuff) > 2 %then %do;
%let syspbuff = %qsubstr(&syspbuff,2,%length(&syspbuff)-2);
%let dlm=%qscan(&syspbuff,1,%str(,),q);
%let return=%qscan(&syspbuff,2,%str(,),q);
%do i=3 %to %sysfunc(countw(&syspbuff,%str(,),q));
%let return=&return.&dlm.%qscan(&syspbuff,&i,%str(,),q);
%end;
%end;
&return.
%mend catx;
%put %catx(|,a,b,c);
a|b|c
%put "%catx(",",a,b,c,d)";
"a","b","c","d"
答案 2 :(得分:1)
不幸的是,我没有看到一个简单的方法。我确实看到你可以在理论上通过FCMP函数传递它,但是因为FCMP不允许真正的变量参数,这也不是理想的,但是......
proc fcmp outlib=work.funcs.funcs;
function catme(delim $, in_string $) $;
length _result $1024;
length _new_delim $1;
_new_delim = scan(in_string,1,delim);
do _i = 1 to countc(in_string,delim);
_result = catx(_new_delim, _result, scan(in_string,_i+1,delim));
end;
return(_result);
endfunc;
quit;
options cmplib=work.funcs;
%let date=10-13-2015;
%put %sysfunc(catme(|,:|The date Is| &date.));
或者在参数中添加引号,然后在CATx之后删除它们。
%sysfunc(dequote(%sysfunc(catt(.... ,"&date."))))
一切都很乱。
答案 3 :(得分:0)
没有dosubl
的
%macro catx() /parmbuff;
%local rc dlm i params OUTSTR QWORD outstr;
%let SYSPBUFF = %qsubstr(&SYSPBUFF,2,%length(&SYSPBUFF)-2);
%let dlm = %qscan(&SYSPBUFF,1,%str(,));
%let params = %qsubstr(&SYSPBUFF,%index(&SYSPBUFF,%str(,))+1);
%let i = 1;
%let QWORD = %scan(&PARAMS,&i,%str(,));
%let OUTSTR = &QWORD;
%do %while(&QWORD ne);
%let i = %eval(&i + 1);
%let QWORD = %scan(&PARAMS,&i,%str(,));
%if &QWORD ne %then %let OUTSTR = &OUTSTR.&DLM.&QWORD;
%end;
%unquote(&OUTSTR)
%mend catx;
%put %catx(%str( ),abc,10 - 1 + 2,def);
更疯狂但显然工作的选项 - 使用%sysfunc(dosubl(...))
和许多宏逻辑来创建一个函数式宏,它以与%sysfunc(catx(...))
相同的方式获取输入,但强制catx处理所有输入作为文本引用并在数据步骤中调用它。
%macro catxt() /parmbuff;
%local rc dlm i params QPARAMS QWORD outstr;
%let SYSPBUFF = %qsubstr(&SYSPBUFF,2,%length(&SYSPBUFF)-2);
%let dlm = %qscan(&SYSPBUFF,1,%str(,));
%let params = %qsubstr(&SYSPBUFF,%index(&SYSPBUFF,%str(,))+1);
%let i = 1;
%let QWORD = "%scan(&PARAMS,&i,%str(,))";
%let QPARAMS = &QWORD;
%do %while(&QWORD ne "");
%let i = %eval(&i + 1);
%let QWORD = "%scan(&PARAMS,&i,%str(,))";
%if &QWORD ne "" %then %let QPARAMS = &QPARAMS,&QWORD;
%end;
%let rc = %sysfunc(dosubl(%str(
data _null_;
call symput("OUTSTR",catx("&dlm",%unquote(&QPARAMS)));
run;
)));
&OUTSTR
%mend catxt;
%put %catxt(%str( ),abc,10 - 1 + 2,def);
虽然这使用数据步骤来执行catx
,但dosubl
允许在通常使用%sysfunc(catx(...))
的任何地方运行整个事件。