【问题标题】:Output to a text file输出到文本文件
【发布时间】:2017-03-31 15:14:29
【问题描述】:

我需要将大量不同的数据集输出到不同的文本文件。数据集共享一些需要输出的公共变量,但也有很多不同的变量。我已将这些不同的变量加载到由空格分隔的宏变量中,以便可以对其进行宏化。

所以我创建了一个宏,它循环遍历数据集并将每个数据集输出到不同的文本文件中。

为此,我在数据步骤中使用了 put 语句。 PUT 语句如下所示:

PUT (all the common variables shared by all the datasets), (macro variable containing all the dataset-specific variables);

例如:

%MACRO OUTPUT();
    %DO N=1 %TO &TABLES_COUNT;
        DATA _NULL_;
            SET &&TABLE&N;
            FILE 'PATH/&&TABLE&N..txt';
            PUT a b c d "&vars";
        RUN;
    %END;
%MEND OUTPUT;

其中 &vars 是宏变量,其中包含在当前循环中输出数据集所需的所有变量。 例如,哪个得到解决:

PUT a b c d special1 special2 special5 ... special329;

现在的问题是,带引号的字符串只能是 262 个字符长。我试图输出的一些数据集有很多变量要输出,这个宏变量是一个带引号的字符串并包含所有这些变量,它将比这长得多。有没有其他方法可以做到这一点?

【问题讨论】:

  • 我认为 PUT 语句可以引用的变量数量没有限制。但是为什么 PUT 语句中间有逗号?
  • 删除了逗号并修改了问题。谢谢指出!
  • 引号也不需要...

标签: sql macros sas proc enterprise-guide


【解决方案1】:

不要在变量名列表中加上引号。

put a b c d &vars ;

您可以输出的变量数量不应有任何限制,但如果输出行的长度过长,SAS 将换行。当前默认行长为 32,767(但旧版本的 SAS 使用 256 作为默认行长)。如果你愿意,你实际上可以设置得更高。例如,您可以使用 1,000,000。上限可能取决于您的操作系统。

FILE "PATH/&&TABLE&N..txt" lrecl=1000000 ;

如果您只是想确保公共变量出现在前面(即您没有排除任何变量),那么您可能根本不需要每个表的变量列表。

DATA _NULL_;
  retain a b c d ;
  SET &&TABLE&N;
  FILE "&PATH/&&TABLE&N..txt" lrecl=1000000;
  put (_all_) (+0) ;
RUN;

【讨论】:

  • 删除了逗号并修改了问题。谢谢指出!
【解决方案2】:

我会解决这个问题,但每个变量有 1 个 put 语句。使用 @ 修饰符,这样您就不会得到新的一行。

例如:

data test;
a=1;
b=2;
c=3;
output;
output;
run;

data _null_;
set test;
put a @;
put b @;
put c @;
put;
run;

将此输出到日志:

800  data _null_;
801  set test;
802  put a @;
803  put b @;
804  put c @;
805  put;
806  run;

1 2 3
1 2 3
NOTE: There were 2 observations read from the data set WORK.TEST.
NOTE: DATA statement used (Total process time):
      real time           0.07 seconds
      cpu time            0.03 seconds

所以修改你的宏以使用这种语法循环遍历两组值。

【讨论】:

  • 删除了逗号并修改了问题。谢谢指出!
【解决方案3】:

不知道为什么你在谈论带引号的字符串:你不会引用 &vars 参数。

put a b c d &vars;

不是

put a b c d "&vars";

那里有一个限制,但要高得多(64k)。

也就是说,我会使用 CALL EXECUTE 以数据驱动的方式执行此操作。这非常简单,一步即可完成,假设您可以在 WHERE 语句中轻松确定要从字典表中输出哪些数据集。这总共有 32kiB 的限制,但如果你真的要复习,你可以很容易地解决它(你可以将不同的位分成多个调用,甚至可以构造调用,以便如果 callstr 达到 32000 长你发出一个调用执行它然后继续)。

这避免了必须管理一堆大型宏变量(您的&VAR 将实际上是&&VAR&N 并且将是许多大型宏变量)。

data test;
  length vars callstr $32767;
  do _n_ = 1 by 1 until (last.memname);
    set sashelp.vcolumn;
    where memname in ('CLASS','CARS');
    by libname memname;
    vars = catx(' ',vars,name);
  end;
  callstr = catx(' ',
    'data _null_;',
    'set',cats(libname,'.',memname),';',
    'file',cats('"c:\temp\',memname,'.txt"'),';',
    'put',vars,';',
    'run;');
    call execute(callstr);
run;

【讨论】: