楼主: yunnandlg
1224 0

[学习分享] SAS编程技巧--获取给定目录下文件信息的宏 [推广有奖]

版主

但问耕耘,莫问收获

院士

0%

还不是VIP/贵宾

-

威望
0
论坛币
251627 个
通用积分
578.6351
学术水平
1667 点
热心指数
1686 点
信用等级
1650 点
经验
173251 点
帖子
1939
精华
0
在线时间
2582 小时
注册时间
2010-8-28
最后登录
2024-4-26

楼主
yunnandlg 在职认证  学生认证  发表于 2016-10-3 00:28:40 |只看作者 |坛友微信交流群|倒序 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币
原文地址:SAS编程技巧--获取给定目录下文件信息的宏作者:hhshnsq
有人在StackOverflow上提问:提问者写了一个SAS宏来获取给定目录下的文件信息,但是代码处理带空格的目录时出错,发帖请求他人的帮助。虽然这是一个很小的功能,但是从回答者的代码可以看到广大SAS程序员的编程功底。

原帖地址:http://stackoverflow.com/questions/1409543/using-sas-macro-to-pipe-a-list-of-filenames-from-a-windows-directory

本人将帖子中的五种实现方法总结如下,并对各种方法加以点评。这个帖子绝对值得一读,尤其是代码里对SAS宏变量中引号的各种处理方法。

方法一:通过SAS提供的文件操作函数 dopen、dnum、dread、dclose。

%macro get_filenames(location);
filename _dir_ "%bquote(&location.)";
data filenames(keep=memname);
  handle=dopen( '_dir_' );
  if handle > 0 then do;
    count=dnum(handle);
    do i=1 to count;
      memname=dread(handle,i);
      output filenames;
    end;
  end;
  rc=dclose(handle);
run;
filename _dir_ clear;
%mend;

%get_filenames(C:temp);         
%get_filenames(C:tempwith space);
%get_filenames(%bquote(C:tempwith'singlequote));

点评:
能够处理路径中包含空格、单引号等特殊命名的情况;
代码可在各种操作系统上运行。

方法二:通过管道技术实现

%macro get_filenames(location);  %*--(1)--*;
   filename pipedir pipe "dir ""%unquote(&location)"" /b" lrecl=32767; %*--(2)--*;
   data filenames;
     infile pipedir truncover;
     input filename $char1000.;
     put filename=;
   run;
   filename pipedir clear;  %*--(3)--*;
%mend;

点评:
能够处理路径中包含空格、单引号等特殊命名的情况;
有些操作系统不支持管道。

方法三:通过管道技术实现
%macro DirList(dir);
      
filename dirpipe pipe "dir ""%unquote(&dir)""*.* /s /-c";
data dir_list(label="Directory Listing [&DIR.]" drop=re_: _line_ date time);
  format Path
         File   $250.
         ModDT  datetime19.
         Size   16.
         _line_ $32000. ;
  if _N_ = 1 then do;
    re_path=prxparse("/Directory of (.+)/");
    re_subd=prxparse("/(dd/dd/dddd)s+(dd:dd [A|P]M)s+s+(S.*)/");
    re_file=prxparse("/(dd/dd/dddd)s+(dd:dd [A|P]M)s+(d+)s+(S.*)/");
    retain re_: path;
    end;
  infile dirpipe lrecl=32000; input; _line_ = _infile_;
  if lengthn(_line_)=0 then delete;
  else
  if prxmatch(re_path, _line_) then do;
    path=prxposn(re_path, 1, _line_);
    end;
  else
  if prxmatch(re_subd, _line_) then do;
    date=input(prxposn(re_subd, 1, _line_), mmddyy10.);
    time=input(prxposn(re_subd, 2, _line_), time6.);
    ModDT=dhms(date, 0, 0, time);
    File=prxposn(re_subd, 3, _line_);
    size = .D;
    if file not in ('.', '..') then output;
    end;
  else
  if prxmatch(re_file, _line_) then do;
    date=input(prxposn(re_file, 1, _line_), mmddyy10.);
    time=input(prxposn(re_file, 2, _line_), time6.);
    ModDT=dhms(date, 0, 0, time);
    size=input(prxposn(re_file, 3, _line_), 16.);
    file=prxposn(re_file, 4, _line_);
    output;
    end;
run;
filename dirpipe clear;
%mend;

点评:
能够处理路径中包含空格、单引号等特殊命名的情况;
能够获取该目录及其子目录下所有文件的信息;
有些操作系统不支持管道;
不同操作系统下dir命令执行结果的格式不同,正则表达式需要修改。

方法四:通过SAS SYSTEM函数执行操作系统命令
注意一定要将 NOXWAIT 和 XSYNC 选项打开。

%macro getdir(dir=,redirect=, switch=);
    options noxwait xsync;
    %if %length(&switch)=0 %then %let switch=b;
    data _null_;
      xcmd='dir "' || "&dir" || '"' || "/&switch " || ">" || "&redirect";
      put 'generated the following command: ' xcmd=;
      rc=system(xcmd);
      put 'result code of above command: ' rc=;
    run;
%mend getdir;

点评:
能够处理路径中包含空格、单引号等特殊命名的情况;
功能比较简单,不如其他方法强大。

方法五:通过SAS提供的文件操作函数 dopen、dnum、dread、dclose。


%macro isDir(iPath=,iQuiet=1);
  %local result dname;

  %let result = 0;

  %if %sysfunc(filename(dname,&iPath)) eq 0 %then %do;
    %if %sysfunc(dopen(&dname)) %then %do;
      %let result = 1;
    %end;
    %else %if not &iQuiet %then %do;
      %put ERROR: ISDIR: %sysfunc(sysmsg());
    %end;
  %end;
  %else %if not &iQuiet %then %do;
    %put ERROR: ISDIR: %sysfunc(sysmsg());
  %end;

  &result

%mend;

%put %isDir(iPath=&sasdir/common/macros);
%put %isDir(iPath=&sasdir/kxjfdkebnefe);
%put %isDir(iPath=&sasdir/kxjfdkebnefe, iQuiet=0);
%put %isDir(iPath=c:temp);



%macro file_list(iPath=, iFilter=, iFiles_only=0, iDelimiter=|);
  %local result did dname cnt num_members filename;

  %let result=;

  %if %sysfunc(filename(dname,&iPath)) eq 0 %then %do;

    %let did = %sysfunc(dopen(&dname));
    %let num_members = %sysfunc(dnum(&did));

    %do cnt=1 %to &num_members;
      %let filename = %sysfunc(dread(&did,&cnt));
      %if "&filename" ne "" %then %do;
        %if &iFiles_only %then %do;
          %if not %isDir(iPath=&iPath/&filename) %then %do;
            %if "&iFilter" ne "" %then %do;
              %if %index(%lowcase(&filename),%lowcase(&iFilter)) %then %do;
                %let result = &result%str(&iDelimiter)&filename;
              %end;
            %end;
            %else %do;
              %let result = &result%str(&iDelimiter)&filename;
            %end;
          %end;
        %end;
        %else %do;
          %if "&iFilter" ne "" %then %do;
            %if %index(%lowcase(&filename),%lowcase(&iFilter)) %then %do;
              %let result = &result%str(&iDelimiter)&filename;
            %end;
          %end;
          %else %do;
            %let result = &result%str(&iDelimiter)&filename;
          %end;
        %end;
      %end;
      %else %do;
        %put ERROR: (CMN_MAC.FILE_LIST) FILE CANNOT BE READ.;
        %put %sysfunc(sysmsg());
      %end;
    %end;

  %end;
  %else %do;
    %put ERROR: (CMN_MAC.FILE_LIST) PATH DOES NOT EXIST OR CANNOT BE OPENED.;
    %put %sysfunc(sysmsg());
  %end;


  %if "&result" ne "" %then %do;
    %substr(&result,2)
  %end;

%mend;



**
** EXAMPLES - HAVENT TESTED THE LAST TWO YET BUT THEY SHOULD WORK IF SYNTAX IS CORRECT
*;

%put %file_list(iPath=c:temp);

%put %file_list(iPath=c:xxdffsds);

%put %file_list(iPath=c:robSASDev, iFilter=a);

%put %file_list(iPath=c:robSASDev,iFiles_only=1);

%put %file_list(iPath=/tmp/unix_sasdir,iFiles_only=1);

data x;
  file_list = "%file_list(iPath=c:temp)";
run;

proc sql noprint;
  insert into my_table values ("%file_list(iPath=c:temp,iDelimiter=%str(","))");
quit;

点评:
能够处理路径中包含空格、单引号等特殊命名的情况;
代码可在各种操作系统上运行;
有完备的错误检查,良好的编程规范,代码值得学习。



二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:SAS编程 delimiter directory questions truncover 程序员 技巧 信息

Cause morning rolls around and it's another day of sun.
清晨不久就会来到,又是阳光明媚的一天。
您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注cda
拉您进交流群

京ICP备16021002-2号 京B2-20170662号 京公网安备 11010802022788号 论坛法律顾问:王进律师 知识产权保护声明   免责及隐私声明

GMT+8, 2024-4-27 11:16