在 defineKey 中使用的宏变量中使用引号

Using quotes in macro variables used in defineKey

我正在尝试围绕这个

的解决方案构建一个宏

我这里的可重现示例没有做任何有用的事情,它只是为了突出我遇到的语法错误。

rc = mx.defineKey(&groups)适用于第一种情况,执行rc = mx.defineKey('grp1','grp2')

然而,在第二种情况下,我定义 &groups 不同但针对相同的值,它失败并出现错误:

NOTE: Line generated by the macro variable "GROUPS". 21
'grp1','grp2' _ 386 _ 200 76 MPRINT(TEST2): rc = mx.defineKey('grp1','grp2'); ERROR: DATA STEP Component Object failure. Aborted during the COMPILATION phase. ERROR 386-185: Expecting an arithmetic expression.

ERROR 200-322: The symbol is not recognized and will be ignored.

ERROR 76-322: Syntax error, statement will be ignored.

这是工作示例,后面是非工作示例。我愿意:

可重现代码:

data have;
input grp1 $ grp2 $ number;
datalines;
a c 3
b d 4
;

%macro test;
data want;
set have;
if _n_ = 1 then do;
    declare hash mx();
    %let groups = 'grp1','grp2';
    %put rc = mx.defineKey(&groups);
    %put rc = mx.defineKey('grp1','grp2');
    rc = mx.defineKey(&groups);
    rc = mx.definedata('number');
    rc = mx.definedone();
end;
run;
%mend;

%test

%macro test2;
data want;
set have;
if _n_ = 1 then do;
    declare hash mx();
    %let grp_list = grp1 grp2;
    %let groups = %str(%')%qsysfunc(tranwrd(&grp_list,%str( ),%str(%',%')))%str(%');
    %put rc = mx.defineKey(&groups);
    %put rc = mx.defineKey('grp1','grp2');
    rc = mx.defineKey(&groups);
    rc = mx.definedata('number');
    rc = mx.definedone();
end;
run;
%mend;

%test2

您需要删除宏引号,因为它会添加不可见的控制字符,这些字符会扰乱您的哈希定义。将相关行更改为:

rc = mx.defineKey(%unquote(&groups));

您也可以考虑定义一个单独的宏来引用每个列表项,并使用双引号而不是单引号,例如

%macro quotelist(list);
  %local i word;
  %do %while(1);
    %let i = %eval(&i + 1);
    %let word = %scan(&list,&i,%str( ));
    %if &word = %then %return;
%sysfunc(quote(&word)) /*De-indent to avoid adding extra spaces*/
  %end;
%mend;

%put %sysfunc(translate(%quotelist(a b c),%str(,),%str( )));

这避免了与解析单引号内的宏变量相关的额外麻烦。

这个问题是宏引用引起的。当您通过 put 将其打印到日志时就可以了。但是,当您使用 defineKey 方法调用它时。 SAS 解析器看到额外的引用。这就是你在执行之前在并发症阶段失败的方式。 (无法识别该符号 - 即宏引用)。如果您删除宏引用,它将起作用。

%macro test2;
data want;
set have;
if _n_ = 1 then do;
    declare hash mx();
    %let grp_list = grp1 grp2;
    %let groups = %str(%')%qsysfunc(tranwrd(&grp_list,%str( ),%str(%',%')))%str(%');
    %put rc = mx.defineKey(&groups);
    %put rc = mx.defineKey('grp1','grp2');
    rc = mx.defineKey(%unquote(&groups));
    rc = mx.definedata('number');
    rc = mx.definedone();
end;
run;
%mend;

不要将宏逻辑嵌入到数据步骤的中间。它可能会让您误以为它在数据步骤 运行 时运行,而不是在数据步骤之前实际运行 运行。

为什么要绕圈圈添加单引号?只需使用双引号。

%macro test2;
%let grp_list = grp1 grp2;
%let groups = "%sysfunc(tranwrd(&grp_list,%str( ),"%str(,)"))";
%put rc = mx.defineKey(&groups);
%put rc = mx.defineKey("grp1","grp2");
data want;
  set have;
  if _n_ = 1 then do;
    declare hash mx();
    rc = mx.defineKey(&groups);
    rc = mx.definedata("number");
    rc = mx.definedone();
  end;
run;
%mend test2;