Sas 空间分隔列表交点

Sas 空间分隔列表交点,sas,sas-macro,Sas,Sas Macro,注:代码在@user667489的备注后编辑,但问题仍然存在 我构建了一个相当简单的宏,将两个空格分隔列表的交集作为一个新的空格分隔列表返回,但由于某些原因,宏的定义返回错误 宏在两个列表中循环并在找到匹配项时保留一个元素(非常简单,不处理重复项或优化) 我无法理解日志,它显示了以下错误消息的组合: 错误:宏关键字LET显示为文本 错误:宏关键字宏显示为文本 你能帮我解决这个问题吗 我也愿意采用一种更高效/稳健/简单的方法来实现相同的输出 可复制日志 使用SAS9.3,我将上述代码放在一个单独的

注:代码在@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