Используя Макрос SAS для передачи по каналу списка имен файлов из каталога Windows

Я видел программы Python, где файл конфигурации код. Если Вы не должны делать ничего специального (условные выражения, и т.д.) это не выглядит очень отличающимся от других стилей конфигурации. например, Я мог сделать файл config.py с материалом как:

num_threads = 13
hostname = 'myhost'

и единственная нагрузка на пользователе, по сравнению с (говорят), что файлы INI, то, что они должны поместить '' вокруг строк. Несомненно Вы могли сделать то же самое на других интерпретируемых языках. Это дает Вам неограниченную способность усложнить Ваш файл конфигурации при необходимости, рискуя тем, чтобы возможно пугать Ваших пользователей.

7
задан Allan Bowe 11 September 2009 в 12:04
поделиться

8 ответов

Вот еще один способ достижения того же результата без использования PIPE.

%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:\temp\with space);
%get_filenames(%bquote(C:\temp\with'singlequote));
14
ответ дан 6 December 2019 в 05:43
поделиться

Внесите несколько следующих изменений, и ваш код будет работать.

%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;

%get_filenames(d:\)          
%get_filenames(d:\your dir)  %*--(4)--*;

(1) Завершите оператор % macro точкой с запятой;

(2) Окружите разрешение макропеременных удвоенными двойными кавычками и % unquote ;

(3) Освободите дескриптор файла, очистив его; и

(4) Не заключайте в одинарные кавычки входной параметр. вместо этого, если необходимо, макросцитируйте.

6
ответ дан 6 December 2019 в 05:43
поделиться

На основе последнего примера на этой странице вместо оператора имени файла попробуйте

%let filrf=pipedir;
%let rc=%sysfunc(filename(filrf,%bquote(dir "&location" /b),pipe));

и вызовите макрос без кавычек:

%get_filenames(c:\temp\with spaces);

Я также пробовал цитировать макрос, но не смог заставить его работать.

3
ответ дан 6 December 2019 в 05:43
поделиться

у меня работает, если я вызываю исходный макрос таким образом

%get_filenames(""C:\Program Files"")

, конечно, мне пришлось добавить точку с запятой в конце оператора % macro .

если ваш каталог содержит запятую, могут случиться неприятности. чтобы исправить это, используйте макрос % str ()

 %get_filenames(%str(C:\temp\comma, fail)) 
2
ответ дан 6 December 2019 в 05:43
поделиться

Мы используем этот небольшой макрос

%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;

Пример вызова

%getdir(dir=c:\temp\,redirect=c:\temp\dir.txt) *run;

Если вы выполняете пакетный запуск и не имеете опции noxwait xsync , задание будет зависать на сервере ждем ответа оператора.

1
ответ дан 6 December 2019 в 05:43
поделиться

here's a quick macro to pull windows-based directory listings into a sas data set.

%macro DirList(dir);

/* %if &SUBDIR eq %then %let subdir=/s; */        /*** &SUBDIR not defined ****/
filename dirpipe pipe "dir &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("/(\d\d\/\d\d\/\d\d\d\d)\s+(\d\d:\d\d [A|P]M)\s+\s+(\S.*)/");
    re_file=prxparse("/(\d\d\/\d\d\/\d\d\d\d)\s+(\d\d:\d\d [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; /*mark subdirectory records*/
    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;

and here's how they get called

%dirlist(c:);
%dirlist(c:\temp);

notice there is no trailing backslash when specifying the base directory. C: not C:\.

3
ответ дан 6 December 2019 в 05:43
поделиться

Вот тот, который расшифровывает порядок цитирования и отмены цитирования:

%let command =%unquote(%str(%')dir "&baseDir.data\*txt"%str(%'));

filename datain pipe &command;

где макропеременная basedir может содержать пробелы и может содержать имена файлов. Эта комбинация % unquote и % str (% ') является часто встречающейся макро-идиомой.

«Что, если в моем каталоге есть одинарные кавычки?»

Для обработки этой ситуации требуется функция макросов, например % bquote (); Продолжая приведенный выше пример, это:

%let command =%unquote(%str(%')dir "%bquote(&baseDir.data\*txt)"%str(%'));

должно это сделать.

Чтобы избежать бесконечных повторений такого рода вопросов, посмотрите статью Яна Уитлока «Серьезный взгляд на макросцитирование», которая доступна здесь ;

Есть (много) других, но это наиболее часто цитируемая. Небольшое примечание: все, что написано Яном Уитлоком, вероятно, того стоит. Он пишет четко и прекрасно разбирается в проблемах SAS.

2
ответ дан 6 December 2019 в 05:43
поделиться

Вот чистая версия кода макроса. Он также позволяет указать, что вы хотите знать только о файлах (а не о папках), и позволяет указать базовый фильтр.Он возвращает список файлов в формате с разделителями, но вы можете легко вставить их в набор данных, используя вставку SQL, если хотите (пример включен, но не протестирован - нет доступа к SAS). Его можно вызвать из любого места - из другого макроса, набора данных, оператора sql ... откуда угодно. Просто добавьте эти два макроса в свою библиотеку автозапуска макросов, и все готово.

Ниже представлены 2 макроса. Макрос% isdir требуется макросу% file_list. Макросы немного больше и сложнее, чем приведенные выше, но они НАМНОГО более гибкие. Плюс они обеспечивают проверку ошибок.

/******************************************************************************
** PROGRAM:  ISDIR.SAS
**
** DESCRIPTION: DETERMINES IF THE SPECIFIED PATH EXISTS OR NOT.
**              RETURNS: 0 IF THE PATH DOES NOT EXIST OR COULD NOT BE OPENED.
**                       1 IF THE PATH EXISTS AND CAN BE OPENED.
**
** PARAMETERS: iPath: THE FULL PATH TO EXAMINE.  NOTE THAT / AND \ ARE TREATED
**                    THE SAME SO &SASDIR/COMMON/MACROS IS THE SAME AS
**                    &SASDIR\COMMON\MACROS.
**
******************************************************************************/

%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);

/******************************************************************************
** PROGRAM:  FILE_LIST.SAS
**
** DESCRIPTION: RETURNS THE LIST OF FILES IN A DIRECTORY SEPERATED BY THE
**              SPECIFIED DELIMITER. RETURNS AN EMPTY STRING IF THE THE 
**              DIRECTORY CAN'T BE READ OR DOES NOT EXIST.
**
** PARAMETERS: iPath      : THE FULL PATH TO EXAMINE.  NOTE THAT / AND \ ARE 
**                          TREATED THE SAME SO &SASDIR/COMMON/MACROS IS THE 
**                          SAME AS &SASDIR\COMMON\MACROS. WORKS WITH BOTH UNIX 
**                          AND WINDOWS.
**             iFilter    : SPECIFY A BASIC FILTER TO THE FILENAMES, NO REGULAR 
**                          EXPRESSIONS OR WILDCARDS.
**             iFiles_only: 0=RETURN FILES AND FOLDERS
**                          1=RETURN FILES ONLY.
**             iDelimiter : SPECIFY THE DELIMITER TO SEPERATE THE RESULTS BY.
******************************************************************************/
/*
** TODO: DOESNT CATER FOR MACRO CHARS IN FILENAMES. FIX SOMETIME.
** TODO: IMPROVE THE FILTER. JUST A SIMPLE IF STATEMENT AT THE MOMENT.
*/
%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;

  /*
  ** RETURN THE RESULT.  TRIM THE LEADING DELIMITER OFF THE FRONT OF THE RESULTS.
  */
  %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:\rob\SASDev\, iFilter=a);

%put %file_list(iPath=c:\rob\SASDev\,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;
2
ответ дан 6 December 2019 в 05:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: