【问题标题】:Set variable to macro variable with ampersand使用&符号将变量设置为宏变量
【发布时间】:2019-11-25 21:22:39
【问题描述】:

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

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

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

【问题讨论】:

    标签: sas sas-macro


    【解决方案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】:

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

      【讨论】:

        【解决方案3】:

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

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-03-08
          • 1970-01-01
          • 1970-01-01
          • 2010-11-04
          • 2023-03-24
          • 2021-11-01
          • 1970-01-01
          相关资源
          最近更新 更多