Sas 将子字符串(可能包含引号等)传递给宏变量

Sas 将子字符串(可能包含引号等)传递给宏变量,sas,Sas,正如我们所知,在宏编译过程中,特殊字符应该被屏蔽。但是如果我想给一个宏变量分配一个动态子字符串呢?像这样: %let mvSubstr = %substr(&mvString, 1, 1); mvString可以包含任何符号,包括不匹配的单引号或双引号 因此,在本例中,程序正常工作: %lev mvString = Test; %let mvSubstr = %substr(&mvString, 1, 1); 在以下情况下,程序不工作,SAS报告错误:文本包含不匹配的引号。:

正如我们所知,在宏编译过程中,特殊字符应该被屏蔽。但是如果我想给一个宏变量分配一个动态子字符串呢?像这样:

%let mvSubstr = %substr(&mvString, 1, 1);
mvString
可以包含任何符号,包括不匹配的单引号或双引号

因此,在本例中,程序正常工作:

%lev mvString = Test;
%let mvSubstr = %substr(&mvString, 1, 1);
在以下情况下,程序不工作,SAS报告
错误:文本包含不匹配的引号。

%lev mvString = %str(%'Test%');
%let mvSubstr = %substr(&mvString, 1, 1);
如何克服这个问题(使程序独立于
mvString
值工作)?

这就是存在的原因。你有很多不同的选择,具体取决于你在做什么

  • %quote
    %nquote
    %bquote
    %nrbquote
    都做了大致相同的事情:屏蔽引号字符和一些其他特殊字符。请参见示例。他们告诉SAS不要注意
    和类似的内容,因此它不必担心匹配的问题。我从来没有看到过使用
    %quote
    而不是
    %bquote
    的理由——B代表“更好”——所以我会用它。它们在执行期间工作,而不是在编译期间
    %nrbquote
    屏蔽宏字符
    &
    %
    ,这意味着它将阻止宏变量内的宏解析
  • 和编译期间的
    %nrstr
    掩码。否则,它们类似于
    %bquote
    %nrbquote
    。如果重要的是在编译期间没有引用,请使用这些
  • 仅屏蔽宏变量(非打开文本),并防止出现所有分辨率。将一个宏变量的值赋给另一个变量通常是最好的方法。重要的是,它不接受
    &
    -您传递宏变量的名称,不带符号或诸如此类的符号(除非宏变量的名称存储在另一个宏变量中)
在您的情况下,需要使用
%bquote
引用子字符串赋值的结果,因此:

%let mvString = %str(%'Test%');
%put &=mvString;

%let mvSubstr = %bquote(%substr(&mvString, 1, 1));
%put &=mvString &=mvSubstr;

如果希望子字符串的值可能包含不匹配的引号或需要宏引号的其他字符,请使用
%QSUBSTR()
函数。当使用
%SCAN()
的结果可能需要引用时,还可以使用
%QSCAN()
函数。当从宏代码中调用其他SAS函数时,还有一个
%QSYSFUNC()
函数。

对于MVSTRING包含需要特殊处理的未屏蔽字符的情况,该如何处理。这需要引用SUBSTR的参数

data _null_;
   call symputx('mvString',"'Test",'G');
   run;
%put %nrbquote(&=mvString);
%let mvSubstr = %bquote(%substr(%superq(mvString), 1, 1));
%put %nrbquote(&=mvString) %nrbquote(&=mvSubstr);

听起来,仅仅使用为这种情况构建的函数需要做很多额外的工作。不确定这是否需要做很多额外的工作(一条宏语句?)。。。虽然
qsubstr
很好,但我还没有看到它。
%qsubstr()
%QSCAN()
是最初的几个宏函数的一部分。当他们引入
%SYSFUNC()
时,出于同样的原因,他们加入了
%QSYSFUNC()
。只是一条注释,%nrbquote实际上不会阻止宏引用解析。我认为NR具有误导性,因为它与%nrstr的作用不同。或者它从来没有正确编程过,他们没有修复它,而是添加了%superq。我不在SAS,因此无法提供示例。我从未发现%nrbquote有什么好的用途。我认为%str、%nrstr、%bquote和%superq是我们需要的全套宏引用函数。同意-我曾想过要提到这一点,但想简化我的回答。当然,考虑输入也是一个好主意(在不同报价选项中的一个很好的例子)。这是一个不同的情况。如果SAS有一个data step函数,可以创建一个宏引用的宏变量,那就太好了。目前,您可以在数据步骤创建引用后添加%LET以应用引用。@Tom我认为
%superq
解决方案更为优越-假设在编写函数/程序时,您的数据可能没有正确引用,并对此进行保护。当然,在创建时单独引用它,但我不认为这是DN示例的重点(这正是他获取未引用值的方式)。@Joe实际上很难将引用不好的值获取到宏变量中。无法将它们传递到参数中,因为宏调用将失败。您不能通过%LET将它们放入,因为这样会失败。主循环孔是datanull和procsql。但是,如果您编写的宏引用现有宏变量而不是参数(或者通过名称而不是值传递宏变量),那么您确实需要编写防御代码。