加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

SAS 宏里各种 QUOTE 函数比较

(2012-11-05 15:30:07)
标签:

杂谈

分类: SAS_Quick_Tips

个人感觉在 SAS 宏语言里最难掌握或者最易混淆的就是各种 QUOTE 函数的用法,刚好上周五帮同事看了一个跟QUOTE 相关的问题,借此机会将 QUOTE 的作用以及所有 QUOTE 函数的用法整理如下。

 

这是几位 SAS 用户在 SGF Paper 里面对 Macro Quoting 的感慨:

I have often said that anyone who thinks macro quoting is simple, probably doesn't understand the problem. 

 

Macro quoting is hard because:
• Quoting is inherently a hard subject.
• The interaction between two languages makes quoting harder.
• The timing issues involved are complex, when the generated language compiles and executes during the
generation of its code.
• There are two macro languages involved - the one which is compiled between %MACRO and %MEND
statements and the one which executes immediately in open SAS code.
• Bugs in the macro facility prevent recognition of a consistent pattern of how macro quoting works.

原文 http://support.sas.com/resources/papers/proceedings10/029-2010.pdf

 

For programmers new to the SAS® Macro Facility, understanding the set of Macro quoting functions and their appropriate uses can be a difficult task. 

原文 http://www2.sas.com/proceedings/forum2007/152-2007.pdf

 

一、为什么要 QUOTE ?

如果你的宏变量取值中包含特殊字符,比如 ; & % ' ( ) 等,那么你必须使用 QUOTE 函数,否则 SAS 代码执行时会出现语法错误、大量宏变量无法替换的警告信息、甚至错误结果。另外,如果你的代码需要在宏语言中处理包含中文字符的 http 链接,那么通常情况下你需要使用 QUOTE 函数。

 

SAS 系统中的特殊字符表如下所示:
blank
)
=
LT
;
(
|
GE
¬
+
AND
GT
^
OR
IN
~
NOT    
%
, (comma)     
     
EQ
&
'
<
NE
#
>
LE

 

比如下面的例子中,我们需要对四个宏变量赋值:

%let var1=a=1;b=2;;
%let var2=a&b;
%let var3=&var2;
%let var4=&var1&var2;


%put &var1;
%put &var2;
%put &var3;
%put &var4;

 

SAS 执行结果:

119  %let var1=a=1;b=2;;
                   -
                   180
ERROR 180-322: Statement is not valid or it is used out of proper order.

WARNING: Apparent symbolic reference B not resolved.
120  %let var2=a&b;
121  %let var3=&var2;
WARNING: Apparent symbolic reference B not resolved.
122  %let var4=&var1&var2;
WARNING: Apparent symbolic reference B not resolved.
WARNING: Apparent symbolic reference B not resolved.
123  %put &var1;
a=1
124  %put &var2;
WARNING: Apparent symbolic reference B not resolved.
a&b
125  %put &var3;
WARNING: Apparent symbolic reference B not resolved.
a&b
126  %put &var4;
WARNING: Apparent symbolic reference B not resolved.
WARNING: Apparent symbolic reference B not resolved.
a=1a&b (注意:此结果不对)

 

正确的结果应当是:

132  %put &var1;
a=1;b=2;
133  %put &var2;
a&b
134  %put &var3;
a&b
135  %put &var4;
a=1;b=2;a&b

 

二、QUOTE 函数原理及其用法

QUOTE 函数的作用是屏蔽这些特殊字符,使得 SAS 系统把这些特殊字符当成普通字符来看待。

 

背后的原理如下:SAS 系统所有的宏变量及其取值都存在一张表中,对于使用了 QUOTE 的字符 SAS 在存储时会给这些特殊字符加上前缀和后缀,SAS 宏处理器对该宏变量做字符串替换时把前缀和后缀去掉,用其原始值来完成替换。

 

Summary of Special Characters and Macro Quoting Functions by Item
 
Group
 Items
 Macro Quoting Functions
A
+ — */<>=¬^|~;, # blank AND OR NOT EQ NE LE LT GE GT IN
 all
        
&% 
 %NRSTR, %NRBQUOTE, %SUPERQ, %NRQUOTE
C
unmatched' “()  
 %BQUOTE, %NRBQUOTE, %SUPERQ, %STR*, %NRSTR*, %QUOTE*, %NRQUOTE
 
Summary of Special Characters and Macro Quoting Functions by Function
 
Function
Affects  Groups
Works At
%STR
A, C*
Macro compilation
%NRSTR
A, B, C*
Macro compilation
%BQUOTE
A, C
Macro execution
%NRBQUOTE
A, B, C
Macro execution
%SUPERQ
A, B, C
Macro execution (prevents resolution)
%QUOTE
A, C*
Macro execution. Requires unmatched quotation marks and parentheses to be marked with a percent sign (%).
%NRQUOTE
A, B, C*
Macro execution. Requires unmatched quotation marks and parentheses to be marked with a percent sign (%).
*Unmatched quotation marks and parentheses must be marked with a percent sign (%) when used with %STR, %NRSTR, %QUOTE, and %NRQUOTE.
 

最常用的宏函数:

  • %STR and %NRSTR
  • %BQUOTE and %NRBQUOTE
  • %SUPERQ

 

下列字符串函数也有其对应的包含 QUOTE 功能的替代函数 (所有 Q 打头的函数):

  • %SCAN and %QSCAN
  • %SUBSTR and %QSUBSTR
  • %UPCASE and %QUPCASE
  • %SYSFUNC and %QSYSFUNC


三、样例代码

大家可以执行下面的代码,看看使用不同 QUOTE 函数得到的结果。

 

有问题的样例代码: 

%let var1=%str(a=1;b=2;);
%let var2=%str(a&b);
%let var3=%str(&var2);
%let var4=%str(&var1&var2);

 

%put &var1;
%put &var2;
%put &var3;
%put &var4;

 


%let var1=%nrstr(a=1;b=2;);
%let var2=%nrstr(a&b);
%let var3=%nrstr(&var2);
%let var4=%nrstr(&var1&var2);

 

%put &var1;
%put &var2;
%put &var3;
%put &var4;

 

正确的样例代码:
%let var1=%str(a=1;b=2;);
%let var2=%nrstr(a&b);
%let var3=%bquote(&var2);
%let var4=%bquote(&var1&var2);

 

%put &var1;
%put &var2;
%put &var3;
%put &var4;

 

有问题的样例代码:

data _null_;
 call symputx('var1', 'a=1;b=2;');
 call symputx('var2', 'a&b');
run;

%let var3=%bquote(&var2);
%let var4=%bquote(&var1&var2);

 

%put &var1;
%put &var2;
%put &var3;
%put &var4;


正确的样例代码:
data _null_;
 call symputx('var1', 'a=1;b=2;');
 call symputx('var2', 'a&b');
run;
%let var1=%superq(var1);
%let var2=%superq(var2);
%let var3=%nrbquote(&var2);
%let var4=%nrbquote(&var1&var2);

 

%put &var1;
%put &var2;
%put &var3;
%put &var4;

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有