문제

DIR 명령에 대한 '위치'인수로 매크로 매개 변수를 수락하기 위해 아래 매크로를 수정하려고합니다. 그러나 중첩 인용문 문제로 인해 올바르게 해결할 수 없습니다. %str ( %')를 사용하는 것은 작동하지 않으며 어떤 이유로 든 인용 기능도하지 않습니다.

매크로는 FilePath가있을 때 잘 작동합니다 공간이 없습니다 (예 : C : temp withnospace) 중간 따옴표가 필요하지 않습니다. 그러나 나는이 매크로가 FilePaths를 위해 일해야합니다 공간과 함께 (예 : 'c : temp space ').

도와주세요!

%macro get_filenames(location)
   filename pipedir pipe   "dir &location. /b " lrecl=32767;
   data filenames;
     infile pipedir truncover;
     input line $char1000.;
   run;
%mend;

%get_filenames(C:\temp\)              /* works */
%get_filenames('C:\temp\with space')  /* doesnt work */
도움이 되었습니까?

해결책

파이프를 사용할 필요없이 동일한 결과를 달성하는 또 다른 방법이 있습니다.

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

다른 팁

다음 몇 가지 변경 사항을 작성하면 코드가 작동합니다.

%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) 입력 매개 변수를 단일 견적하지 마십시오. 대신 마크로 견적, 필요한 경우.

마지막 샘플을 기반으로합니다 이 페이지, 파일 이름 명령문 대신 시도해보십시오

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

인용문을 사용하지 않고 매크로에 전화하십시오.

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

나는 또한 매크로 인용을 시도했지만 그것을 작동시킬 수 없었습니다.

다음은 Windows 기반 디렉토리 목록을 SAS 데이터 세트로 끌어 올리는 빠른 매크로입니다.

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

그리고 여기 그들이 어떻게 전화를 받는가가 있습니다

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

기본 디렉토리를 지정할 때 후행 백 슬래시가 없습니다. C: ~ 아니다 C:\.

이 방법으로 원래 매크로를 호출하면 저에게 효과적입니다.

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

물론 나는 끝에 세미콜론을 추가해야했다. %macro 성명.

디렉토리에 쉼표가 포함되어 있으면 나쁜 일이 발생합니다. 수정하려면 사용하십시오 %str() 매크로

 %get_filenames(%str(C:\temp\comma, fail)) 

순수한 매크로 코드 버전이 있습니다. 또한 파일 (폴더가 아닌 파일)에 대해서만 알고 싶다는 것을 지정하고 기본 필터를 지정할 수 있습니다. 파일 목록을 구분 형식으로 반환하지만 원하는 경우 SQL Insert를 사용하여 데이터 세트에 쉽게 삽입 할 수 있습니다 (예제 포함이지만 테스트되지 않음 -SAS 액세스 ATM). 다른 매크로, 데이터 세트, SQL 명령문 내에서 어디서나 호출 할 수 있습니다. 이 두 매크로를 매크로 Autocall 라이브러리에 추가하면 가야합니다.

아래에는 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;

다음은 인용 및 인용문의 명령을 방해하지 않는 것입니다.

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

filename datain pipe &command;

매크로 변수 기반에 공백이 포함될 수 있으며 파일 이름도 마찬가지입니다. 이 조합%unquote 그리고 %str(%') 자주 발생하는 매크로 관용구입니다.

"내 딥에 단일 인용문이 있다면 어떨까요?"

이 상황을 처리하려면 매크로 인용 기능이 필요합니다. %bquote();위의 예를 계속하면 다음과 같습니다.

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

해야합니다.

이런 종류의 질문에 대한 무한한 반복을 피하려면 이안 휘트 록 (Ian Whitlock)의 논문, 매크로 인용문을 진지하게 살펴보십시오. 여기;

다른 사람들이 많지만 이것은 가장 널리 인용됩니다. 약간의 메모 : Ian Whitlock의 모든 것이 가치가있을 것입니다. 그는 명확하게 글을 쓰고 SAS 문제에 대한 그의 이해는 대단합니다.

우리는이 작은 매크로를 사용합니다

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

배치로 실행하고 있지 않은 경우 option noxwait xsync 작업은 운영자 응답을 기다리는 서버에 매달려 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top