SAS Цикл и импорт каждого файла Объединение двух наборов кода - PullRequest
1 голос
/ 05 апреля 2019

У меня есть 2 набора кода SAS, которые оба работают правильно.

Один - это макрос, который может циклически проходить по каталогу и находить все файлы, которые соответствуют определенному расширению.

Другойэто файл, который может открыть один из zip-файлов и импортировать его в таблицу.

Я хотел бы объединить два набора кодов и иметь возможность циклически перебирать файлы, импортируя их все в набор данных SAS.Набор данных может иметь номер 1 - (количество файлов).

Я пытался добавить код в макрос напрямую, но у меня проблемы с каталогами, в которых есть пробел, и весь код выполняется правильно.

Код 1:

%macro drive(dir,ext); 
   %local cnt filrf rc did memcnt name; 
   %let cnt=0;          

   %let filrf=mydir;    
   %let rc=%sysfunc(filename(filrf,&dir)); 
   %let did=%sysfunc(dopen(&filrf));
    %if &did ne 0 %then %do;   
   %let memcnt=%sysfunc(dnum(&did));    

    %do i=1 %to &memcnt;              

      %let name=%qscan(%qsysfunc(dread(&did,&i)),-1,.);                    

      %if %qupcase(%qsysfunc(dread(&did,&i))) ne %qupcase(&name) %then %do;
       %if %superq(ext) = %superq(name) %then %do;                         
          %let cnt=%eval(&cnt+1);       
          %put %qsysfunc(dread(&did,&i));  
          proc import datafile="&dir\%qsysfunc(dread(&did,&i))" out=dsn&cnt 
           dbms=csv replace;            
          run;          
       %end; 
      %end;  

    %end;
      %end;
  %else %put &dir cannot be open.;
  %let rc=%sysfunc(dclose(&did));      

 %mend drive;

%drive(/opt/sasdata/mnt/FM/folder,Z) ;

Код 2:

Filename Comgzip Pipe "gzip -cd /opt/sasdata/mnt/FM/folder/20181218.Z";
Data DataSet15;
Infile ComgZip  dsd dlm=',' missover firstobs=1;

Input 
ContractID $
ProdID $
IssueDate $
Market $
TaxClsCode $
BenEffDate $
PriceDate $
AnnuitDOB $
AnnuitAge
BenYear
BenMonth ;
run;

Ответы [ 2 ]

2 голосов
/ 06 апреля 2019

Поскольку вы собираетесь генерировать код, нет необходимости использовать такой сложный макрос для поиска файлов.Этот первый макрос слишком сложен, потому что он использует код макроса для вызова функций SAS.Используйте что-то, что просто использует код SAS (вместо макрокода) и генерирует набор данных найденных файлов.

%macro files(dir,ext,dsn=files);
filename mydir "&dir";
data &dsn ;
  length name $256 ;
  did=dopen('mydir');
  if did then do;   
    do i=1 to dnum(did);              
      name="&dir\"||dread(did,i);
      if upcase(scan(name,-1,'.'))=%upcase("&ext") then output;
    end;
    rc=dclose(did);
  end;
  keep name;
run;
filename mydir;
%mend files;

Затем используйте набор данных имен файлов для генерации кода для импорта каждого файла.Либо напрямую сгенерируйте код для импорта каждого файла, либо создайте простой макрос, который импортирует один файл и генерирует вызовы к этому макросу.

Проблема с пробелами в именах файлов, вероятно, влияет на оператор FILENAME во втором фрагменте кода.,Просто добавьте еще кавычки.

%macro readfile(filename,dsn);
filename comgzip pipe "gzip -cd ""&filename"" ";
data &dsn;
  infile comgzip dsd truncover;
  input 
    ContractID $
    ProdID $
    IssueDate $
    Market $
    TaxClsCode $
    BenEffDate $
    PriceDate $
    AnnuitDOB $
    AnnuitAge
    BenYear
    BenMonth 
  ;
run;
%mend readfile;

Так что теперь вы можете генерировать звонки с чем-то вроде этого:

%files(/opt/sasdata/mnt/FM/folder,Z) ;
data _null_;
  set files;
  n+1;
  call execute(cats('%readfile(',name,',',cats('dsn',n),')'));
run;
0 голосов
/ 06 апреля 2019

Прямо сейчас у меня нет SAS, чтобы проверить это, но я предполагаю, что ваша проблема заключается в отсутствии кавычек вокруг путей. В частности, имя файла оператора:

Filename Comgzip Pipe "gzip -cd /opt/sasdata/mnt/FM/folder/20181218.Z";

Предположим, что ваше имя пути имеет пробел и выглядит так:

/opt/sasdata/mnt/FM/my folder/20181218.Z

Затем вы хотите, чтобы код, созданный вашим макросом, выглядел примерно так (чтобы путь к файлу был заключен в двойные кавычки, а вся команда была заключена в одинарные кавычки):

Filename Comgzip Pipe 'gzip -cd "/opt/sasdata/mnt/FM/my folder/20181218.Z" ';

Тогда возникает проблема: как вы можете разрешить свои макропеременные, когда они заключены в одинарные кавычки? Вы можете сделать это просто используя нотацию %str(%'). Этот синтаксис просто разрешается в одну кавычку, так что вы можете поместить их в любой конец кода, содержащего двойные кавычки, которые вы все еще хотите разрешить, и это должно решить проблему. Последняя строка кода будет выглядеть примерно так:

Filename Comgzip Pipe %str(%')gzip -cd "&full_path_and_filename" %str(%');
...