Sas 空间分隔列表交点
注:代码在@user667489的备注后编辑,但问题仍然存在 我构建了一个相当简单的宏,将两个空格分隔列表的交集作为一个新的空格分隔列表返回,但由于某些原因,宏的定义返回错误 宏在两个列表中循环并在找到匹配项时保留一个元素(非常简单,不处理重复项或优化) 我无法理解日志,它显示了以下错误消息的组合: 错误:宏关键字LET显示为文本 错误:宏关键字宏显示为文本 你能帮我解决这个问题吗 我也愿意采用一种更高效/稳健/简单的方法来实现相同的输出 可复制日志 使用SAS9.3,我将上述代码放在一个单独的程序中,这样它就不会被污染、保存项目、关闭并重新打开。打开程序,单击运行按钮,下面是完整的日志:Sas 空间分隔列表交点,sas,sas-macro,Sas,Sas Macro,注:代码在@user667489的备注后编辑,但问题仍然存在 我构建了一个相当简单的宏,将两个空格分隔列表的交集作为一个新的空格分隔列表返回,但由于某些原因,宏的定义返回错误 宏在两个列表中循环并在找到匹配项时保留一个元素(非常简单,不处理重复项或优化) 我无法理解日志,它显示了以下错误消息的组合: 错误:宏关键字LET显示为文本 错误:宏关键字宏显示为文本 你能帮我解决这个问题吗 我也愿意采用一种更高效/稳健/简单的方法来实现相同的输出 可复制日志 使用SAS9.3,我将上述代码放在一个单独的
1 The SAS System 09:50 Monday, January 22, 2018
1 ;*';*";*/;quit;run;
2 OPTIONS PAGENO=MIN;
3 %LET _CLIENTTASKLABEL='Program3';
ERROR: Macro keyword LET appears as text.
4 %LET _CLIENTPROJECTPATH='F:\CI\Projects\Wealth Indicators\106 Explore DIM_PHYSICALPERSON\SAS\Rework_table_auto2.egp';
ERROR: Macro keyword LET appears as text.
5 %LET _CLIENTPROJECTNAME='Rework_table_auto2.egp';
ERROR: Macro keyword LET appears as text.
6 %LET _SASPROGRAMFILE=;
ERROR: Macro keyword LET appears as text.
7
8 ODS _ALL_ CLOSE;
9 OPTIONS DEV=ACTIVEX;
10 GOPTIONS XPIXELS=0 YPIXELS=0;
11 FILENAME EGSR TEMP;
12 ODS tagsets.sasreport13(ID=EGSR) FILE=EGSR STYLE=HtmlBlue
12 ! STYLESHEET=(URL="file:///C:/Program%20Files/SASHome/x86/SASEnterpriseGuide/5.1/Styles/HtmlBlue.css") NOGTITLE NOGFOOTNOTE
12 ! GPATH=&sasworklocation ENCODING=UTF8 options(rolap="on");
13
14 GOPTIONS ACCESSIBLE;
15 %macro list_intersection
ERROR: Macro keyword MACRO appears as text.
16 (list1= /* space separated list, or unique term */
17 ,list2= /* space separated list, or unique term */
18 );
19 %local output;
ERROR: Macro keyword LOCAL appears as text.
20 %local i;
ERROR: Macro keyword LOCAL appears as text.
21 %local j;
ERROR: Macro keyword LOCAL appears as text.
22 %let i = 1;
ERROR: Macro keyword LET appears as text.
23 %let j = 1;
ERROR: Macro keyword LET appears as text.
24 %do %while (%length(%scan(&list1,&i)));
ERROR: Macro keyword DO appears as text.
25 %do %while (%length(%scan(&list2,&j)));
ERROR: Macro keyword DO appears as text.
26 %if (%scan(&list1,&i) = %scan(&list2,&j)) %then
ERROR: Macro keyword IF appears as text.
27 %let output = &output %scan(&list1,&i);
28 %let j = %eval(&j+1);
ERROR: Macro keyword LET appears as text.
29 %end;
ERROR: Macro keyword END appears as text.
30 %let i = %eval(&i+1);
ERROR: Macro keyword LET appears as text.
31 %end;
ERROR: Macro keyword END appears as text.
32 &output
33 %mend;
ERROR: Macro keyword MEND appears as text.
34
35 GOPTIONS NOACCESSIBLE;
36 %LET _CLIENTTASKLABEL=;
ERROR: Macro keyword LET appears as text.
37 %LET _CLIENTPROJECTPATH=;
2 The SAS System 09:50 Monday, January 22, 2018
ERROR: Macro keyword LET appears as text.
38 %LET _CLIENTPROJECTNAME=;
ERROR: Macro keyword LET appears as text.
39 %LET _SASPROGRAMFILE=;
ERROR: Macro keyword LET appears as text.
40
41 ;*';*";*/;quit;run;
42 ODS _ALL_ CLOSE;
43
44
45 QUIT; RUN;
46
编辑前的初始代码:
有几件事立即引人注目:
%local
设置宏变量的值。而不是%local i=1代码>必须编写两个单独的语句:%local i;%设i=1代码><代码>%local
将宏变量初始化为空字符串
%if
语句中的括号不平衡%let j=%eval(&j+1)代码>进入外部%do%,同时执行循环
%scan
仅使用空格作为分隔符-它默认为空格加( + & ! $ * ) ; ^ - / , % |代码>
%macro list_intersection
(list1= /* space separated list, or unique term */
,list2= /* space separated list, or unique term */
);
%local output;
%local i;
%local j;
%let i = 1;
%do %while (%length(%scan(&list1,&i,%str( ))));
%let j = 1;
%do %while (%length(%scan(&list2,&j,%str( ))));
%if %scan(&list1,&i,%str( )) = %scan(&list2,&j,%str( )) %then
%let output = &output %scan(&list1,&i,%str( ));
%let j = %eval(&j+1);
%end;
%let i = %eval(&i+1);
%end;
&output
%mend;
%put %list_intersection(list1=1 2 3,list2=2 3 4);
您可以使用SAS函数来简化这一过程。使用
COUNTW()
函数查找%DO
循环的上限。使用FINDW()
函数测试是否在其他列表中找到单词
%macro list_intersection
(list1 /* space separated list of terms */
,list2 /* space separated list of terms */
);
%local output i next ;
%do i=1 %to %sysfunc(countw(&list1,%str( ))) ;
%let next=%scan(&list1,&i,%str( ));
%if %sysfunc(findw(&list2,&next,,s)) %then %let output=&output &next ;
%end;
&output
%mend;
您可以在findw()
调用中包含i
修饰符,使其不区分大小写。您还可以测试输出字符串中是否已存在该单词,以消除重复项
%macro list_intersection_nodups
(list1 /* space separated list of terms */
,list2 /* space separated list of terms */
);
%local output i next ;
%do i=1 %to %sysfunc(countw(&list1,%str( ))) ;
%let next=%scan(&list1,&i,%str( ));
%if %sysfunc(findw(&list2,&next,,si)) and not %sysfunc(findw(&output,&next,,si))
%then %let output=&output &next ;
%end;
&output
%mend;
例如:
274 %put %list_intersection_nodups(A B a C,a c d);
A C
谢谢,我纠正了这些错误(请参见编辑后的答案),代码仍然失败,但是我的if语句只有一条语句需要有条件地执行(
%let output=&output%scan(&list1,&I);
),其他语句已经包装在%do…%结束代码>。我误解了你的第三点吗?对不起,我的错误。谢谢你的耐心@user667489,你的解决方案有效而且更健壮,我的问题似乎有一部分是EG错误(应用程序需要完全关闭并重新启动),这并没有使它更容易解决!请举例说明如何运行宏以及完整的日志输出结果。我在编写复杂的SAS代码时添加了日志。我编写了一个%generate\u table\u from_list()
宏,然后您尝试编写的宏可以通过两个调用从输入列表创建表来实现,然后是一个PROC SQL
将它们相交,然后选择将结果放入输出变量中。此实现无法在无法生成中间步骤或过程的环境中使用,但对我来说几乎从来都不是问题。至于错误:宏关键字LET显示为文本。
,我会重新启动EG(或重新连接到应用服务器)。谢谢Nickolay,我确实必须重新启动EG,我错误地认为在不关闭EG的情况下重新启动项目就足够了。当我在路上建立一个<代码> %的独特的findw
%macro list_intersection_nodups
(list1 /* space separated list of terms */
,list2 /* space separated list of terms */
);
%local output i next ;
%do i=1 %to %sysfunc(countw(&list1,%str( ))) ;
%let next=%scan(&list1,&i,%str( ));
%if %sysfunc(findw(&list2,&next,,si)) and not %sysfunc(findw(&output,&next,,si))
%then %let output=&output &next ;
%end;
&output
%mend;
274 %put %list_intersection_nodups(A B a C,a c d);
A C