SAS-在字符串上放置空白

时间:2018-10-24 09:16:26

标签: string sas

我有一个脚本来编写如下所示的SAS程序(txt):

    /********* Import excel spreadsheet with model sepcs *****************/
    proc import file = "&mydir\sample.xls" out = model dbms = xls replace;
    run;
/********* Create program model *****************/
    data model;         
    set model;          
        dlb = resolve(dlb); 
        dub = resolve(dub); 
    run;                
    data model;
    set model;
        where2 = tranwrd(where,"="," ");
        where2 = tranwrd(where2,"<"," ");
        where2 = tranwrd(where2,">"," ");
        nword = countw(where2);
        bounds = trim(dlb)!!" "!!trim(dub);
        bounds = tranwrd(bounds,"="," "); 
        bounds = tranwrd(bounds,"<"," ");
        bounds = tranwrd(bounds,">"," ");  
        nbounds = countw(bounds);                                 
    run;
proc sql noprint;
    select max(nword) into: max_word from model ;
    select max(nbounds) into: max_aux from model ;                                              
    select name into: list_var separated by " " from dictionary.columns where libname = "WORK" and memname = "IMP" ;
quit;
/******* Generate Model ********/
    %macro generate_model;                                                                                                                          
        data model;                                                                                                                                     
        set model;                                                                                                                                      
        attrib wherev length = $500.;                                                                                                                   
            do i = 1 to countw(where2);                                                                                                                     
                %do j = 1 %to %sysfunc(countw(&list_var));                                                                                                  
                    if upcase(scan(where2,i)) = "%upcase(%scan(&list_var,&j))" and scan(where2,i) not in ("0","1","2","3","4","5","6","7","8","9") then do; 
                        if missing(wherev) then wherev = trim(scan(where2,i));                                                                              
                        else if index(wherev,trim(scan(where2,i))) = 0 then do;                                                                             
                            wherev = trim(wherev)!!" "!!trim(scan(where2,i));                                                                               
                        end;                                                                                                                                
                    end;                                                                                                                                    
                %end;                                                                                                                                       
            end;                                                                                                                                            
        drop i where2;                                                                                                                                  
        run;                                                                                                                                                                                                                                                                                       
        data model;                                                                                                                                     
        set model;                                                                                                                                      
        attrib aux length = $500.;                                                                                                                      
            do i = 1 to countw(bounds);                                                                                                                     
                %do j = 1 %to %sysfunc(countw(&list_var));                                                                                                  
                    if upcase(scan(bounds,i)) = "%upcase(%scan(&list_var,&j))" and scan(bounds,i) not in ("0","1","2","3","4","5","6","7","8","9") then do; 
                        if missing(aux) then aux = trim(scan(bounds,i));                                                                                    
                        else if index(aux,trim(scan(bounds,i))) = 0 then do;                                                                                
                            aux = trim(aux)!!" "!!trim(scan(bounds,i));                                                                                     
                        end;                                                                                                                                
                    end;                                                                                                                                    
                %end;                                                                                                                                       
            end;                                                                                                                                            
        drop i bounds;                                                                                                                                  
        run;                                                                                                                                            
    %mend;                                                                                                                                          
    %generate_model;

data outem.bound;
set outem.model;
attrib txt length = $2000.;
    txt = "******************Macros for variable"!!trim(dep)!!"******;";
    output;
    txt = "%"!!"macro bound"!!trim(dep)!!";";
    output;
    if not missing(lb) then do;
        txt ="LB="!!trim(lb)!!";";
        output;
    end;
    if not missing(ub) then do;
        txt ="UB="!!trim(ub)!!";";
        output;
    end;
    if not missing(dlb) and not missing(lb) then do;
        txt ="LB=MAX(LB,"!!trim(dlb)!!");";
        output;
    end;
    if not missing(dlb) and missing(lb) then do;
        txt ="LB="!!trim(dlb)!!";";
        output;
    end;
    if not missing(dub) and not missing(ub) then do;
        txt ="UB=MIN(UB,"!!trim(dub)!!");";
        output;
    end;
    if not missing(dub) and missing(ub) then do;
        txt ="UB="!!trim(dub)!!";";
        output;
    end;
    txt = "%"!!"mend;";
    output;run;

data outem.imp;
    set outem.bound;
    file "&mydir\3_generate_models\3_model.sas" lrecl = 2000;
    put txt;
run;

程序运行正常,但是我无法在UBLB之前放置空格。

输出看起来像这样:

%macro boundHC0340;
LB=           1;
UB=           9;
%mend;

但是我想得到这个:

%macro boundHC0340;
    LB=           1;
    UB=           9;
%mend;

该代码已经尝试过在UBLB之前放置空白,但是到目前为止我无法管理。

我可以在其中放置其他字符和字符串。我只是不能在UBLB之前留空格以产生缩进代码。

我尝试过这样的事情:

txt ="      LB="!!trim(lb)!!";";

但是LB之前的空白没有任何作用。

但是如果我这样写:

   txt ="******LB="!!trim(lb)!!";";

我的程序上出现星号。

我在这里想念的东西有什么想法吗?

非常感谢您的支持。

最诚挚的问候

Ps:这是示例xls文件的超链接:sample.xls

2 个答案:

答案 0 :(得分:1)

我认为这是SAS在使用put语句时默认为变量$w.格式应用左对齐的结果。您可以通过在put语句中应用格式并指定要使用的对齐方式来覆盖此内容:

data _null_;
  file "%sysfunc(pathname(work))\example.txt";
  a = "       text here";

  /*Approach 1 - default behaviour*/
  /*No leading spaces on this line in output file (default)*/
  put a;


  /*Approach 2 - $varying + right alignment*/
  /*We need to right align text while preserving the number of leading spaces, so use $varying. */
  /*If every line is the same length, we can use $w. instead*/
  /*Use -r to override the default format alignment*/
  varlen = length(a);
  put a $varying2000.-r varlen;

  /*Approach 3 - manually specify indentation*/
  /*Alternatively - ditch the leading spaces and tell SAS which column to start at*/
  put @4 a;
run;

尝试更改代码的最后一部分,使其看起来像这样(适当地修复路径和数据集名称):

data bound;
set model;
attrib txt length = $2000.;
    txt = "******************Macros for variable"!!trim(dep)!!"******;";
    output;
    txt = "%"!!"macro bound"!!trim(dep)!!";";
    output;
    if not missing(lb) then do;
        /* LEADING SPACES ADDED HERE */
        /* LEADING SPACES ADDED HERE */
        /* LEADING SPACES ADDED HERE */
        txt ="    LB="!!trim(lb)!!";";
        output;
    end;
    if not missing(ub) then do;
        /* LEADING SPACES ADDED HERE */
        /* LEADING SPACES ADDED HERE */
        /* LEADING SPACES ADDED HERE */
        txt ="    UB="!!trim(ub)!!";";
        output;
    end;
    if not missing(dlb) and not missing(lb) then do;
        txt ="LB=MAX(LB,"!!trim(dlb)!!");";
        output;
    end;
    if not missing(dlb) and missing(lb) then do;
        txt ="LB="!!trim(dlb)!!";";
        output;
    end;
    if not missing(dub) and not missing(ub) then do;
        txt ="UB=MIN(UB,"!!trim(dub)!!");";
        output;
    end;
    if not missing(dub) and missing(ub) then do;
        txt ="UB="!!trim(dub)!!";";
        output;
    end;
    txt = "%"!!"mend;";
    output;
run;

data _null_;
    set bound;
    file "%sysfunc(pathname(work))\example.sas" lrecl = 2000;
    varlen = length(txt);
    put txt $varying2000.-r varlen;
run;

x "notepad ""%sysfunc(pathname(work))\example.sas""";

example.sas的内容(基于示例xls):

******************Macros for variableHC0340******;
%macro boundHC0340;
    LB=           1;
    UB=           9;
%mend;

答案 1 :(得分:1)

假设您已使用要查看的值构建了变量TXT,则只需在最后一步中添加格式。为避免编写很多无用的尾随空白,请使用$VARYING格式。您需要计算字符串的长度才能使用该格式。

data outem.imp;
    set outem.bound;
    file "&mydir\3_generate_models\3_model.sas" lrecl = 2000;
    length= lengthn(txt);
    put txt $varying2000. length;
run;

但是,跳过所有串联并使用PUT语句本身的功能直接从数据中编写程序可能会更容易。然后,您可以使用指针控件(@3)或命名值lb=PUT语句的其他功能来格式化程序文件。

data _null_;
  set outem.model;
  file "&mydir\3_generate_models\3_model.sas" ;
  put 72*'*' ';'
    / '* Macros for variable ' dep ';'
    / 72*'*' ';'
    / '%macro bound' dep ';'
  ;
  if not missing(lb) then put @3 lb= ';' ;
  if not missing(ub) then put @3 ub= ';' ;
  if not missing(dlb) and not missing(lb) then put
    @3 'LB=MAX(LB,' dlb ');'
  ;
  if not missing(dlb) and missing(lb) then put
    @3 'LB=' dlb ';'
  ;
  if not missing(dub) and not missing(ub) then put
    @3 'UB=MIN(UB,' dub ');'
  ;
  if not missing(dub) and missing(ub) then put
    @3 'UB=' dub ';'
  ;
  put '%mend bound' dep ';';
run;

尽管查看了这些IF语句的逻辑,但为什么不将它们简化为:

put @3 'LB=MAX(' lb ',' dlb ');' ;
put @3 'UB=MIN(' ub ',' dub ');' ;