将变量设置为带有&符号的宏变量

时间:2019-11-25 21:22:39

标签: sas sas-macro

不确定标题的标题,因为标题仍然很模糊,但是我正在做的是。

PROC SQL NOPRINT;
    SELECT LABEL INTO :head
    FROM dictionary.columns
    WHERE UPCASE(MEMNAME)='PROCSQLDATA' AND UPCASE(NAME)=%UPCASE("&var.");
QUIT;

DATA want;
    SET have;
    head="%SUPERQ(&head.)";
RUN;

所以我在代码中所做的就是将宏变量“ head”设置为变量“&var”的标签。在数据集“ procsqldata”中。因此,假设我要放入proc sql的变量之一的标签是Adam&Steve。如何在不引发错误的情况下将其设置为数据集中的变量。我尝试作弊的一种方法行不通,因为我可能做错了

 %LET steve='&steve';

但这似乎不起作用,由于某种原因,它只是在数据步骤上进行了无限循环。

3 个答案:

答案 0 :(得分:1)

%SUPERQ接受参数的名称,然后在宏引用的上下文中检索其值。

如果所使用的符号名称(head)是具有更多上下文含义的名称(例如var_label),则可能会更好地进行长期了解。另外,您的DICIONARY.COLUMNS查询应包含libname=的条件。注意:LIBNAME和MEMNAME值在DICTIONARY.COLUMNS中始终为大写。 Name是列名,可以大小写混合,需要upcase进行比较,以确保名称相等。

PROC SQL NOPRINT;
    SELECT LABEL INTO :var_label
    FROM dictionary.columns
    WHERE 
       LIBNAME = 'WORK' and
       MEMNAME = 'PROCSQLDATA' and
       UPCASE(NAME)=%UPCASE("&var.")
    ;
QUIT;

data labels;
  set have;
  head_label = "%superq(var_label)";
run;

&中的SUPERQ表示要获取其值的宏变量的名称是另一个宏变量的值。

 %let p = %nrstr(Some value & That%'s that);
 %let q = p;
 %let v = %superq(&q);
 %put &=v;
 -------- LOG -------
 V=Some value & That's that

&q成为p%superq检索到p的值以分配给v

注意:在某些情况下,您可以使用VLABELVLABELX函数在运行的数据步骤中检索变量的标签。

 data have;
   label weight = 'Weight (kg)';
   retain weight .;

   weight_label_way1 = vlabel ( weight );
   weight_label_way2 = vlabelx('weight');
 run;

答案 1 :(得分:1)

几点。

首先,%SUPERQ()函数希望宏变量的名称引用。因此,如果您写:

%superq(&head)

宏处理器将评估宏变量HEAD并将该值用作要引用其值的宏变量的名称。而是这样写:

%superq(head)

第二个宏触发器不会在外部使用单引号的字符串内部进行评估。所以这句话:

%let steve='&steve';

会将宏变量Steve设置为单引号,“&”号,s,t,....单引号。

但是请注意,如果宏用单引号引起来,则它们不具有对宏处理器隐藏文本的属性。像这样:

%str(%')%superq(head)%str(%') 

%bquote('%superq(head)')

将生成用引号引起来的宏变量HEAD的值。

所以您可能会摆脱:

head = %bquote('%superq(head)') ;

尽管有时宏引用可能会混淆SAS编译器(尤其是在宏内部),所以现在您有了单引号来保护与号,并且可能需要删除宏引用。

head = %unquote(%bquote('%superq(head)')) ;

但是真正的解决方案是根本不使用宏引用它。

可以使用SYMGET()函数提取值。

head = symget('head');

(由于设置了函数调用,请确保为数据集变量HEAD或SAS设置一个长度,使其默认为$ 200)。

或者更好的方法是将标签保留在变量开头,而不是通过将其填充到宏变量中而使自己(和其他所有人)迷惑,以便随后将其拉回到真实变量中。

PROC SQL NOPRINT;
create table label as SELECT LABEL 
    FROM dictionary.columns
    WHERE LIBNAME='MYLIB' and MEMNAME='PROCSQLDATA' and UPCASE(NAME)=%UPCASE("&var.")
;
QUIT;

DATA want;
  SET have;
  if _n_=1 then set label;
  head = label;
  drop label;
run;

答案 2 :(得分:0)

会有一个报价功能可以解决此问题,但是我永远都不记得它们的全部功能,出于我自己和同事的理智,我发现最好避免它们。

在这种情况下,您根本不需要将宏变量解析为字符串文字(即head = "&head";);您可以使用SYMGET

DATA want;
  SET have;
  head = SYMGET('head');
RUN;

在此处查看SYMGET函数的文档:

https://documentation.sas.com/?docsetId=mcrolref&docsetTarget=n00cqfgax81a11n1oww7hwno4aae.htm&docsetVersion=9.4&locale=en

关于不相关的注意事项,您还应该阅读本页末尾的“字典表和性能”部分:

https://documentation.sas.com/?cdcId=pgmsascdc&cdcVersion=9.4_3.5&docsetId=sqlproc&docsetTarget=n02s19q65mw08gn140bwfdh7spx7.htm&locale=en

如果您从UPCASE子句中删除了WHERE函数,您可能会惊讶于第一个查询的运行速度有多快。