I am trying to amend the macro below to accept a macro parameter as the 'location' argument for a dir command. However I cannot get it to resolve correctly due to the nested quotes issue. Using %str(%') does not work, neither do quoting functions for some reason.
我正在尝试修改下面的宏,以接受一个宏参数作为dir命令的“位置”参数。但是由于嵌套引号问题,我无法使它正确地解析。使用%str(%')不起作用,出于某种原因,引用函数也不起作用。
The macro will work fine when the filepath has no spaces (eg C:\temp\withnospace) as the middle quotes aren't needed. However I need this macro to work for filepaths with spaces (eg 'C:\temp\with space\').
当文件路径没有空格(例如C:\temp\ nospace)时,宏就可以正常工作,因为中间的引号不需要。但是,我需要这个宏来处理带空格的文件路径(例如'C:\temp\with space\')。
Please help!
请帮助!
%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 */
8 个解决方案
#1
14
Here's another way of achieving the same result without needing to use a 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));
#2
6
Make the following several changes and your code will work.
做以下几个更改,您的代码就会工作。
%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) End the %macro
statement with a semi-colon;
(1)以分号结束%宏语句;
(2) Surround the macro variable resolution with doubled-up double quotes and %unquote
;
(2)用双引号和%unquote包围宏变量分辨率;
(3) Release the file handle by clearing it; and
(3)清理文件句柄,释放文件句柄;和
(4) Don't single quote your input parameter. macro quote instead, if necessary.
(4)不要只引用输入参数。如果有必要的话,用宏引用代替。
#3
3
Based on the last sample on this page, instead of the filename statement, try
基于本页上的最后一个示例,而不是filename语句,try
%let filrf=pipedir;
%let rc=%sysfunc(filename(filrf,%bquote(dir "&location" /b),pipe));
and call the macro without using quotes:
不使用引号调用宏:
%get_filenames(c:\temp\with spaces);
I also tried macro quoting, but couldn't get it to work.
我也尝试了宏观引用,但是没有成功。
#4
3
here's a quick macro to pull windows-based directory listings into a sas data set.
这里有一个快速的宏,可以将基于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;
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:\
.
请注意,在指定基目录时没有尾部反斜杠。C:C:\。
#5
2
it works for me if i call the original macro this way
如果我用这种方式调用原始的宏,它就会工作
%get_filenames(""C:\Program Files"")
of course i had to add the semicolon at the end of the %macro
statement.
当然,我必须在%macro语句的末尾添加分号。
if your directory contains a comma, bad things happen. to fix, use the %str()
macro
如果您的目录包含一个逗号,就会发生糟糕的事情。要修复,请使用%str()宏
%get_filenames(%str(C:\temp\comma, fail))
#6
2
Here's a pure macro code version. It also allows you to specify that you only want to know about files (and not folders) and lets you specify a basic filter. It returns the list of files in a delimited format but you can easily insert these into a dataset using SQL insert if you wanted to (example included but not tested - no SAS access atm). It can be called from anywhere - within another macro, a dataset, an sql statement... wherever. Just add these two macros to your macro autocall library and you're right to go.
这是一个纯宏代码版本。它还允许您指定您只想知道文件(而不是文件夹),并允许您指定一个基本的过滤器。它以带分隔符的格式返回文件列表,但是如果您想要的话,可以使用SQL insert将这些文件插入到数据集中(例如,包含但没有经过测试——没有SAS access atm)。它可以从任何地方调用——在另一个宏、数据集、sql语句中……无论在哪里。只要将这两个宏添加到宏自动调用库中,就可以了。
There are 2 macros below. The %isdir macro is required by the %file_list macro. The macros are a bit larger and more complex than the above but they are MUCH more flexible. Plus they provide error checking.
下面有两个宏。%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;
#7
2
Here's one that unscrambles the order of quoting and unquoting:
这里有一个解读引用和不引用顺序的例子:
%let command =%unquote(%str(%')dir "&baseDir.data\*txt"%str(%'));
filename datain pipe &command;
where macro variable basedir can contain spaces and so can the filenames. This combination of %unquote
and %str(%')
is a frequently occuring macro idiom.
宏变量basedir可以包含空格,文件名也可以包含空格。这种%unquote和%str(%')的组合是经常出现的宏习惯用法。
"what if I have single quote in my dir?"
“如果我在我的目录里有一个引用呢?”
Handling this situation requires a macro quoting function, such as %bquote();
Continuing the example above, this:
处理这种情况需要一个宏引用函数,例如%bquote();继续上面的例子,这个:
%let command =%unquote(%str(%')dir "%bquote(&baseDir.data\*txt)"%str(%'));
should do it.
应该这样做。
To avoid infinite iterations of this kind of question, look at Ian Whitlock's paper, A Serious Look at Macro Quoting, which is available here;
为了避免这类问题的无限重复,看看伊恩·惠特洛克的论文,认真研究宏观引用,这里有;
There are (many) others, but this is the most widely cited. A little note: anything by Ian Whitlock is probably worthwhile. He writes clearly and his understanding of SAS issues is awesome.
有(许多)其他的,但这是最广泛引用的。小提示:伊恩·惠特洛克(Ian Whitlock)的任何作品都可能值得一看。他写得很清楚,他对SAS问题的理解非常棒。
#8
1
We use this little macro
我们使用这个小宏
%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;
Sample Call
示例调用
%getdir(dir=c:\temp\,redirect=c:\temp\dir.txt) *run;
If you run in batch and don't have the option noxwait xsync
the job will hang on the server waiting for an operator response.
如果您以批处理方式运行,并且没有noxwait xsync的选项,作业将挂在服务器上等待操作符响应。
#1
14
Here's another way of achieving the same result without needing to use a 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));
#2
6
Make the following several changes and your code will work.
做以下几个更改,您的代码就会工作。
%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) End the %macro
statement with a semi-colon;
(1)以分号结束%宏语句;
(2) Surround the macro variable resolution with doubled-up double quotes and %unquote
;
(2)用双引号和%unquote包围宏变量分辨率;
(3) Release the file handle by clearing it; and
(3)清理文件句柄,释放文件句柄;和
(4) Don't single quote your input parameter. macro quote instead, if necessary.
(4)不要只引用输入参数。如果有必要的话,用宏引用代替。
#3
3
Based on the last sample on this page, instead of the filename statement, try
基于本页上的最后一个示例,而不是filename语句,try
%let filrf=pipedir;
%let rc=%sysfunc(filename(filrf,%bquote(dir "&location" /b),pipe));
and call the macro without using quotes:
不使用引号调用宏:
%get_filenames(c:\temp\with spaces);
I also tried macro quoting, but couldn't get it to work.
我也尝试了宏观引用,但是没有成功。
#4
3
here's a quick macro to pull windows-based directory listings into a sas data set.
这里有一个快速的宏,可以将基于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;
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:\
.
请注意,在指定基目录时没有尾部反斜杠。C:C:\。
#5
2
it works for me if i call the original macro this way
如果我用这种方式调用原始的宏,它就会工作
%get_filenames(""C:\Program Files"")
of course i had to add the semicolon at the end of the %macro
statement.
当然,我必须在%macro语句的末尾添加分号。
if your directory contains a comma, bad things happen. to fix, use the %str()
macro
如果您的目录包含一个逗号,就会发生糟糕的事情。要修复,请使用%str()宏
%get_filenames(%str(C:\temp\comma, fail))
#6
2
Here's a pure macro code version. It also allows you to specify that you only want to know about files (and not folders) and lets you specify a basic filter. It returns the list of files in a delimited format but you can easily insert these into a dataset using SQL insert if you wanted to (example included but not tested - no SAS access atm). It can be called from anywhere - within another macro, a dataset, an sql statement... wherever. Just add these two macros to your macro autocall library and you're right to go.
这是一个纯宏代码版本。它还允许您指定您只想知道文件(而不是文件夹),并允许您指定一个基本的过滤器。它以带分隔符的格式返回文件列表,但是如果您想要的话,可以使用SQL insert将这些文件插入到数据集中(例如,包含但没有经过测试——没有SAS access atm)。它可以从任何地方调用——在另一个宏、数据集、sql语句中……无论在哪里。只要将这两个宏添加到宏自动调用库中,就可以了。
There are 2 macros below. The %isdir macro is required by the %file_list macro. The macros are a bit larger and more complex than the above but they are MUCH more flexible. Plus they provide error checking.
下面有两个宏。%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;
#7
2
Here's one that unscrambles the order of quoting and unquoting:
这里有一个解读引用和不引用顺序的例子:
%let command =%unquote(%str(%')dir "&baseDir.data\*txt"%str(%'));
filename datain pipe &command;
where macro variable basedir can contain spaces and so can the filenames. This combination of %unquote
and %str(%')
is a frequently occuring macro idiom.
宏变量basedir可以包含空格,文件名也可以包含空格。这种%unquote和%str(%')的组合是经常出现的宏习惯用法。
"what if I have single quote in my dir?"
“如果我在我的目录里有一个引用呢?”
Handling this situation requires a macro quoting function, such as %bquote();
Continuing the example above, this:
处理这种情况需要一个宏引用函数,例如%bquote();继续上面的例子,这个:
%let command =%unquote(%str(%')dir "%bquote(&baseDir.data\*txt)"%str(%'));
should do it.
应该这样做。
To avoid infinite iterations of this kind of question, look at Ian Whitlock's paper, A Serious Look at Macro Quoting, which is available here;
为了避免这类问题的无限重复,看看伊恩·惠特洛克的论文,认真研究宏观引用,这里有;
There are (many) others, but this is the most widely cited. A little note: anything by Ian Whitlock is probably worthwhile. He writes clearly and his understanding of SAS issues is awesome.
有(许多)其他的,但这是最广泛引用的。小提示:伊恩·惠特洛克(Ian Whitlock)的任何作品都可能值得一看。他写得很清楚,他对SAS问题的理解非常棒。
#8
1
We use this little macro
我们使用这个小宏
%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;
Sample Call
示例调用
%getdir(dir=c:\temp\,redirect=c:\temp\dir.txt) *run;
If you run in batch and don't have the option noxwait xsync
the job will hang on the server waiting for an operator response.
如果您以批处理方式运行,并且没有noxwait xsync的选项,作业将挂在服务器上等待操作符响应。