一:global宏變量和local宏變量
例子1:
%let outside = AAA;
%macro one;
%global inone;
%let inone = BBB;
%mend one;
%macro two;
%let intwo = CCC;
%mend two;
%macro last;
%one
%two
%put &outside &inone &intwo;
%mend last;
%last

注意到outside(屬于global變量)這個宏變量是在宏外面定義的,所以也不需要申明global;
宏變量inone雖然是在宏里面定義的,但是它用global申明了,所以也屬于global宏變量
例子2:
%macro allyr3(start=10,stop=14);
data allyear;
set
%do year = &start %to &stop;
yr&year(in=in&year)
%end;;
year = 2000
%do year = &start %to &stop;
+ (in&year*&year)
%end;;
run;
%mend allyr3;
%let year = FRED;
%put The global value of year is &year;
%allyr3(start=12, stop=14)
%put The global value of year is &year;

例子3:
在上面的這段代碼中,year的值會被15給代替
所以這種情況下,我們可以對宏里面的year進行申明,這樣就不會導(dǎo)致宏變量之間發(fā)生沖突
*申明local變量,避免宏變量之間沖突;
%macro allyr4(start=10,stop=14);
%local year;
%let year=&start;
data allyear;
set
%do year = &start %to &stop;
yr&year(in=in&year)
%end;;
year = 2000
%do year = &start %to &stop;
+ (in&year*&year)
%end;;
run;
%mend allyr4;
%let year = FRED;
%put The global value of year is &year;
%allyr4(start=12, stop=14)
%put The global value of year is &year;

二:宏變量和data步交互
對于數(shù)據(jù)集中的數(shù)據(jù),我們有時候可能想將某個變量的值做成宏變量,比如下面這樣
data age;
set sashelp.class(where=(name='Jane'));
%let jane_age = age;
run;
但是上面這段代碼是不會輸出正確結(jié)果的,原因還是那個宏先編譯的內(nèi)在執(zhí)行機制。
需要注意的是,call symputx并不是宏水平語句,而是一個可執(zhí)行的DATA步驟例程,因此它允許你在data步執(zhí)行的時候,直接根據(jù)數(shù)據(jù)集的變量賦值給宏變量。
CALL SYMPUTX(macro-variable, value <, symbol-table>);
CALL SYMPUTX的第一個參數(shù)可以是字符串、可以是字符變量、也可以是字符型變量和字符串的結(jié)合。
CALL SYMPUTX的第二個參數(shù)可以是字符串、可以是字符變量、也可以是字符型變量和字符串的結(jié)合。
下面我們看下上面的這3種情形:
①:第一和第二個參數(shù)都是字符串,需要注意的是,在將值賦予給宏變量的時候,會自動去除值前后的空格。



可以看到值前后的空格都被自動去除了。
②:第一個和第二個參數(shù)都是變量
說實話,一開始根據(jù)SASHELP的解釋,我根本沒看懂怎么用。下面看例子就清楚了



解釋:當(dāng)?shù)谝粋€參數(shù)是數(shù)據(jù)集中的某個變量的時候,它的值就是宏變量的名稱(在這里就是變量mvar的值"MAIN"和“NUM”,注意不是變量mvar)
第二個參數(shù)就是數(shù)據(jù)集變量的值(在這里就是變量nhigh的值)。
需要注意的是如果第二個參數(shù),變量的值是數(shù)值型的話,SAS會自動先轉(zhuǎn)換成字符型再輸出,還會在log窗口輸出一個note。
還需要注意到是第一個參數(shù)如果是數(shù)據(jù)集的某個變量,那么變量的值必須是字符型或者說符合SAS命名規(guī)則的值,比如mvar都是數(shù)字,SAS就會報錯。
if mod(n,2)=0 then mvar="MAIN";
else mvar=777;

這就是第二種情況。
③:字符型變量和字符串的結(jié)合;

這段程序會輸出19個宏變量(數(shù)據(jù)集里面有19條觀測)

上面是CALL SYMPUTX參數(shù)的解析,講到CALL SYMPUTX,還有一個就是CALL SYMPUT,前者是后者的升級版,主要區(qū)別在于如果第二個參數(shù)是數(shù)值型的,CALL SYMPUTX能直接轉(zhuǎn)換成字符型在進行處理,并且不會在log里報note;
CALL SYMPUTX的第三個參數(shù)能控制生成的宏變量是什么類型的,但是CALL SYMPUT不行。
data _null_;
x=5;
call symput('x1',x);
call symput('x2',trim(left(put(x,6.))));
call symputx('x3',x);
run;
%put The vertical bars show leading and trailing blanks.;
%put Using SYMPUT X1 is |&x1|;
%put Using SYMPUT with TRIM LEFT PUT X2 is |&x2|;
%put Using SYMPUTX X3 is |&x3|;

這條log就是第一個CALL SYMPUT產(chǎn)生的。
除了trim/left函數(shù),還可以通過這種形式生成宏變量:
VAR2="SAS";
call symputx('x4',catt(VAR2," programmer "));

att函數(shù)的作用是去除末尾的空格,比如下面的程序,輸出結(jié)果是SAS前面的空格也被去除了,但是這是call symputx的功勞,而不是catt的功勞。
VAR2=" SAS";
call symputx('x4',catt(VAR2," programmer "));
上面這段程序輸出結(jié)果跟上張圖片一樣。
運用catt函數(shù)還需要注意一點,我就不舉例子了。
