使用%nowpath宏获取当前SAS路径
前几天学习了一个叫mypath的宏,其实现了将当前sas程序的路径定义为一个宏变量、以方便后续调用路径的功能。查了下相关资料,在《Generating Program-Stamped Output in an Interactive SAS Session》中,也有个叫fullpath的宏,是提取当前路径为宏变量后进行应用。
个人觉得这2个实现路径提取功能的宏及其中的编程技巧挺有用的,拿出来分享一下。
1.%nowpath
1.1
将%mypath和%fullpath作了小小改动、整合成了下面的宏%nowpath
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | %macro nowpath; %global fullpath nowpath; /*定义为global,为后续调用准备*/ proc sql noprint; select xpath into : fullpath /*选取全路径*/ from dictionary.extfiles /*dictionary.extfiles包含SAS路径信息*/ where substr(fileref,4) eq ( select max(substr(fileref,4)) /*max()保证选取最新(当前)路劲*/ from dictionary.extfiles where substr(fileref,1,1) eq "#" and index(xpath,".sas") gt 0 ); quit; /*选取当前路径*/ %let nowpath=%substr(&fullpath,1,%eval(%length(&fullpath)-%length(%scan(&fullpath,-1,\)))); %put The Full Path is: &fullpath; %put The Now Path is: &nowpath; %mend nowpath; |
这里面有一大关键点,就是dictionary.extfiles的使用。
关于dictionary.extfiles,个人没能查到详细的资料,下面是个人结合各种零碎介绍及一些测试做的理解(如有不对或不祥的地方,非常感谢大家能指出或补充):
- dictionary.extfiles会记录一些SAS的路径,包括系统、人为定义的路径,及运行(存储)的SAS文件的路径,fileref分别标记为SASAUTOS、MYAUTOS及#LN00000类型,并将路径名其存储于xpath变量中。
- 对于#LN类型,其后五位数字按时间依次递增,最新的一个路径的数字标号最大。
所以找出最大的#LN路径即为当前SAS文件的路径。
下图是引用《Generating Program-Stamped Output in an Interactive SAS Session》中的图:
再来看%nowpath:
- 使用“where substr(fileref,1,1) eq “#” and index(xpath,”.sas”) gt 0”来保证选取的类型#LN
- 使用“max(substr(fileref,4)”找出最新(即当前)路径
从而得到全路径:fullpath; 然后在通过substr和length函数的使用得到当前路径:nowpath
所以运行
1 | %nowpath; |
log中得到:
The Full Path is: F:\1.SAS\0.My SAS\0.My Blog_Statistics with SAS\12.宏nowpath\nowpath.sas The Now Path is: F:\1.SAS\0.My SAS\0.My Blog_Statistics with SAS\12.宏nowpath\
1.2
而如《Generating Program-Stamped Output in an Interactive SAS Session》介绍,使用dictionary.extfiles是SAS V8的主要办法,SAS 9提供了2个environment variables:sas_execfilename和sas_execfilepath可以直接获取当前SAS文件名和路径。
于是可用下面的代码:
1 2 3 4 5 6 7 8 9 10 11 | %macro nowpath2; %global fullpath2 nowpath2; %let name=%sysget(sas_execfilename); %let fullpath=%sysget(sas_execfilepath); %let nowpath = %substr(&fullpath,1,%eval(%length(&fullpath) - %length(&name) ) ); %put fullpath2=&fullpath; %put nowpath2=&nowpath; %mend nowpath2; |
2.宏nowpath的作用
上述宏就是实现将当前路径存储为宏变量,有哪些可取之处呢?
- 方便高效。在后续程序中若要使用当前路径的话,只需“&nowpath”,既省时省力又准确。
- 规范、可移植性强。对于一个常用的标准的宏程序来说,其需要保证很强的可移植性和稳健性,当将程序转移到其他文件位置或设备时,使用此种方法便不需人为的对路径进行改动,而能直接运行。
举个简单的例子:
以后我写某个博客,数据及现有程序路径如下:
利用现有Example_data要生成:
一些SAS数据集文件(.sas7bdat)、一些图形文件(.png)、一些结果数据(.xls),并将其相应的存储到datasets、plot、out_data文件夹下。
代码中就会有许多需要定义路径的过程,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 | data _null_; datap=dcreate("datasets","&nowpath"); /*在“&nowpath”路径下建立文件夹datasets*/ run; data _null_; out_p=dcreate("out_data","&nowpath"); /*在“&nowpath”路径下建立文件夹out_data*/ run; libname blog "&nowpath\datasets\"; proc import datafile="&nowpath.example_data.xls" out=blog.eg_data replace; getnames=yes; run; |
这样,路径调用很方便,而且即使以后如果中间的路径有所更改,或者在其他机器上运行,只要有数据和程序,不必修改仍可保证无误运行。
3.题外话:关于DICTIONARY tables(词典表)
从这个样例宏,再次可以看出使用DICTIONARY tables能实现很好的功能。
- DICTIONARY tables在PROC SQL中使用,通过其可以获取SAS系统信息,包括逻辑库、数据集、系统选项等等详细信息。
- 经常会用到的是dictionary.columns,dictionary.tables等,读取其中关于我们所需的数据及变量等信息进入宏变量中,再做进一步的后续批量处理的工作。
- 另外,DICTIONARY tables对应于SASHELP views(如dictionary.columns对应于sashelp.vcolumn),这样,在data step中我们也可以进行类似操作,十分方便、有效。
关于其详细介绍可以参见SASHELP文档及《SAS SQL 9.2 Procedure User Guide》中的“Accessing SAS System Information by Using DICTIONARY Tables”有关内容。
参考文献:
http://cos.name/cn/topic/103604
《Generating Program-Stamped Output in an Interactive SAS Session》
《SAS SQL 9.2 Procedure User Guide》
data _null_;
datap=dcreate(“datasets”,”&nowpath”); /*在“&nowpath”路径下建立文件夹datasets*/
run;
如何先判断文件夹是否存在,如没有再创建?
[回复]
别担心,没有它会创建,有了它也不会删除重建,也不报错。
[回复]
hssnow 回复:
9月 18th, 2011 at 22:22
呵呵,谢谢解答啊~
[回复]