使用&符号将变量设置为宏变量

Set variable to macro variable with ampersand

不确定如何命名这个标题,因为标题仍然很模糊,但我正在做的是。

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"。因此,假设我投入过程 sql 的其中一个变量的标签是 Adam&Steve。如何在不引发错误的情况下将其设置为数据集中的变量。我试图作弊的一种方法是行不通的,因为我可能做错了

 %LET steve='&steve';

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

会有一个引用函数可以解决这个问题,但我永远记不起它们都是做什么的,为了我自己和同事的理智,我发现最好避免使用它们。

在这种情况下,您根本不需要将宏变量解析为字符串文字(即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

关于一个不相关的说明,您还应该阅读本页末尾的 'DICTIONARY Tables and Performance' 部分:

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

如果从 WHERE 子句中删除 UPCASE 函数,您的第一个查询 运行 会快多少,您可能会感到惊讶。

%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;

几点。

首先,%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;