我们知道,在宏编译期间应该屏蔽特殊字符。但是,如果我想为宏变量分配动态子字符串呢?像这样:
%let mvSubstr = %substr(&mvString, 1, 1);
mvString
可以包含任何符号,包括不匹配的单引号或双引号。
因此,在此示例程序中正常工作:
%lev mvString = Test;
%let mvSubstr = %substr(&mvString, 1, 1);
在以下情况下,程序无效,SAS报告ERROR: Literal contains unmatched quote.
:
%lev mvString = %str(%'Test%');
%let mvSubstr = %substr(&mvString, 1, 1);
如何解决这个问题(让程序独立于mvString
值工作)?
答案 0 :(得分:4)
如果您希望子字符串的值可能包含不匹配的引号或其他需要宏引用的字符,请使用%QSUBSTR()
函数。当使用%QSCAN()
的结果可能需要引用时,还可以使用%SCAN()
函数。并且在宏代码中调用其他SAS函数时有%QSYSFUNC()
函数。
答案 1 :(得分:3)
这就是macro quoting存在的原因。你有很多不同的选择,具体取决于你正在做什么。
%quote
,%nrquote
,%bquote
和%nrbquote
- 大致完全相同:屏蔽引号字符和其他一些特殊字符。例如,参见documentation for %bquote/nrbquote
。他们告诉SAS不要注意'
和类似的东西,所以它不担心匹配的东西。我从未见过使用%quote
超过%bquote
的理由--B代表'更好' - 所以我会用它。它们在执行期间工作,而不是编译。 %nrbquote
会屏蔽宏字符&
和%
,这意味着它会阻止宏变量中的宏进行解析。%str
和%nrstr
掩码。否则它们与%bquote
和%nrbquote
类似。如果在编译期间没有引号是很重要的,请使用这些。%superq
仅屏蔽宏变量(不是打开文本)并阻止所有分辨率发生。这通常是将一个宏变量的值分配给另一个变量的最佳方法。重要的是不需要&
- 您传递宏变量的名称,没有符号或诸如此类的东西(除非宏变量的名称存储在另一个宏变量中)。 / LI>
在您的情况下,您需要使用%bquote
来引用子字符串赋值的结果,所以:
%let mvString = %str(%'Test%');
%put &=mvString;
%let mvSubstr = %bquote(%substr(&mvString, 1, 1));
%put &=mvString &=mvSubstr;
答案 2 :(得分:1)
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);