现在chatgpt确实很厉害,有什么需求直接跟它说,很多时候都能给你一个相对正确的程序,即使有些是错误的,也能给你一些启发,感觉到后面,真的不需要我们写多少代码了。
最近自己有一个需求,就是获取文件夹下的sas程序名,然后套上一个宏程序名,直接复制就好了,就没必要一个一个写了。
%macro list_files(path=, ext=);
%local filrf rc did memcnt name i;
%let rc = %sysfunc(filename(filrf,&path));
%let did = %sysfunc(dopen(&filrf));
%if &did ne 0 %then %do;
%let memcnt = %sysfunc(dnum(&did));
%put &memcnt;
%do i = 1 %to &memcnt;
%let name = %sysfunc(dread(&did,&i));
%put &name;
%if %upcase(%sysfunc(prxmatch(/&ext$/i, &name))) > 0 %then %do;
%put %nrstr(%%)comb(datsn=&name);
%end;
%end;
%end;
%else %put Directory &path could not be opened or does not exist;
%let rc = %sysfunc(dclose(&did));
%let rc = %sysfunc(filename(filrf));
%mend list_files;
%list_files(path=D:\Practice, ext=sas);
接下来解释下代码:
1)%let rc = %sysfunc(filename(filrf,&path));
以前我看到SASHELP举的例子里面一直遇到这个rc,还以为是什么特殊的宏变量,但是我换成其他宏变量也能运行,说明并不是什么系统宏变量。搜了一下,这个rc更可能是“runcomm”的缩写――即名词“run command”(运行命令)的简写。
然后这个filename是一个函数,而不是一个语句(filename有语句和函数两种作用),作为函数的时候,它的作用是给外部文件或者文件夹指定一个文件引用路径。
重点关注一下fileref和filename这两个参数。
fileref指定分配给外部文件或文件夹的fileref,在data步中,这个fileref可以是一个字符表达式,一个用单引号括起来的字符串。
在宏里面的时候,比如在%SYSFUNC 函数的时候,fileref就是一个宏变量的名称,但是不需要用&,比如上面的程序就没有用&filrf,也不需要用引号括起来。
filename可以是指定外部文件的字符常量、变量或表达式,在我们的程序中就是一个物理路径指向具体的文件夹。
2)%let did = %sysfunc(dopen(&filrf));
dopen函数的作用是打开一个文件夹,并返回是否打开的指令,比如0或1,然后函数里面的参数也是一个外部文件或文件夹的fileref
所以我们直接打开上面已经设定好的fileref,这时候需要用&调用设定好的宏变量。
有人好奇如果我如果不用filename能不能直接打开文件夹呢?测试了一下是不行的,
%let did = %sysfunc(dopen(D:\t.sas));
不管我是直接指定一个文件夹还是指定一个具体的文件,都显示无法打开,而且这个fileref还不能超过8个字符。
所以必须先通过filename生成一个fileref,相当于先生成一个钥匙,有了这个钥匙我们才能打开文件夹的门。看SASHELP举的例子也都是先通过filename生成一个fileref,如果实在不好理解的话,知道怎么用就可以了。工作中那么多东西也做不到都了解,很多时候都是遇到了再去查找。
3)%let memcnt = %sysfunc(dnum(&did));
dnum函数的作用是返回文件夹下有多少个文件(任何文件形式)
4)%let name = %sysfunc(dread(&did,&i));
dread函数的作用就是返回文件夹下文件的名称,包括具体的文件格式,比如test.xlsx,比如我这个文件夹下有23个文件,然后有各种各样的文件格式。
最后我们用正则匹配sas程序,然后输出到log窗口,注意这里我用了两个%,大家在输出含有%的字符的时候,也可以试试这种方式。
大家打开文件夹之后,记得关上文件夹,这样应该是避免一直打开占据内存什么的。
当然了,既然可以搜索SAS程序名,肯定也可以搜索其他文件名,比如我们搜索excel文件
%list_files(path=D:\Practice, ext=xlsx);