2016-08-29 41 views
0

正如我们所知,在宏编译过程中应该隐藏特殊字符。但是如果我想将一个动态子串分配给一个宏变量呢?像这样:将一个子字符串(可能包含引号等)传递给宏变量

%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值)?

回答

4

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

3

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

  • %quote%nrquote%bquote,并%nrbquote - 所有做大致相同的事情:面具引号字符和其他一些特殊字符。例如参见documentation for %bquote/nrbquote。他们告诉SAS不要注意'和类似的东西,所以它不用担心匹配的东西。我从来没有见过使用%quote而不是%bquote的理由--B代表“更好” - 所以我会使用它。他们在执行期间工作,而不是汇编%nrbquote掩盖宏字符&%,这意味着它将阻止宏变量内的宏解析。
  • %str and %nrstr mask 汇编。否则它们与%bquote%nrbquote相似。如果在编译过程中没有引用是很重要的,请使用它们。
  • %superq仅屏蔽了一个宏变量(未打开文本)并防止发生所有分辨率。将一个宏变量的值分配给另一个变量通常是最好的方法。重要的是不要采用&--你通过宏变量的名称,没有&符或什么都不(除非宏变量的名称存储在另一个宏变量中)。

在你的情况,你就需要使用%bquote引用的子任务的结果,所以:

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

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

听起来像只是使用为这种情况构建的函数做了很多额外的工作。 – Tom

+0

不确定是否有很多额外的工作(一个宏语句?)...'qsubstr'虽然很好,我还没有看到。 – Joe

+0

'%QSUBSTR()'和'%QSCAN()'是最初几个宏函数的一部分。当他们引入'%SYSFUNC()'时,出于同样的原因,他们包含'%QSYSFUNC()'。 – Tom

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); 
+0

同意 - 我曾考虑过提及那个,但想简化我的答案。绝对是一个好主意来考虑输入(以及不同报价选项的差异的一个很好的例子)。 – Joe

+0

这是一种不同的情况。如果SAS具有可创建宏引用宏变量的数据步功能,那将会很不错。现在,您可以添加%LET,以在数据步骤创建后应用引用。 – Tom

+0

@Tom我认为'%superq'解决方案更加优越 - 假设你的数据在编写你的函数/程序时可能没有被适当地引用,并且防止这种情况发生。在创建过程中另外引用它,但我不认为这就是DN在这里的例子(这就是他如何得到一个没有引号的值)。 – Joe

相关问题