BookmarkSubscribeRSS Feed
venkibhu14
Calcite | Level 5

Hi All,

 

Are there any ways to convert the executed code from the log to a SAS file (with or with out a indentation)?

 

For example: The below is the macro executed code printed in the log. Can it be possible to send this to a SAS file which can be executable?

 

venkibhu14_0-1659634395405.png

 

Thanks in Advance,

 

Venkat.

3 REPLIES 3
sbxkoenk
SAS Super FREQ

Hello,

 

I do not think there's an easy way.

Do you want to do this because you do not have the source code of a compiled macro?

Be cautious as one execution of the macro might only reveal 10% of its code.

 

Anyway, you could send the log to an external file, like here :

filename myfile '/users/myid/mydir/mylog';
proc printto log=myfile;
run;

Then import that log-file into a SAS-dataset (every line of the log becomes one record, and the full line is in one variable).

You can use the $VARYINGw. informat to do that, or just columns-input 1 - 150 (for example).

Then filter out the records (i.e. observations) starting with the string 'MPRINT(TEMP):' and remove that part with substr function.

Then put (file statement and put statements) the records of your new dataset to an external file again.
That external file should be a valid program that you can %INCLUDE.

 

Thanks,

Koen

Tom
Super User Tom
Super User

You can easily get 90% there. Keep the lines that start with MPRINT(.  Remove the MPRINT(...): from the start of the lines.

data _null_;
  infile 'myfile.log';
  file 'myfile.sas';
  input ;
  if _infile_ ne ' ' and _infile_=:'MPRINT(';
  _infile_=substrn(_infile_,length(scan(_infile_,1,' '))+1);
  put _infile_;
run;

But watch out for extremely long statements, like PROC SQL SELECT statements.

 

Tom
Super User Tom
Super User

If you can re-run the program instead then it is even easier.  Just use the MFILE option.

https://documentation.sas.com/doc/en/vdmmlcdc/8.1/mcrolref/p1dhqw0i5yj2m8n15opapnwteqra.htm

 

You can direct MPRINT output to an external file by also using the MFILE option and assigning the fileref MPrint to that file. For more information, see MFILE System Option.

Example: Directing MPRINT Output to an External File

Adding these statements before the macro call in the previous program sends the MPRINT output to the file DebugMac when the SAS session ends.
options mfile mprint;
filename mprint 'debugmac';

Try this example at home:

filename ds2post url 'https://raw.githubusercontent.com/sasutils/macros/master/ds2post.sas';
%include ds2post;

filename mprint temp;
options mfile mprint;
%ds2post(sashelp.class);

Here is what was written to the fileref MPRINT.

 310        options nomfile;
 311        data _null_;
 312          infile mprint;
 313          input;
 314          put _infile_;
 315        run;
 
 NOTE: The infile MPRINT is:
       Filename=/saswork/SAS_work9085000092C9_odaws03-usw2.oda.sas.com/#LN00038,
       Owner Name=tom.xxx,Group Name=oda,
       Access Permission=-rw-r--r--,
       Last Modified=04Aug2022:15:26:47,
       File Size (bytes)=3377
 
 *----------------------------------------------------------------------------;
 * Get member label in format of dataset option. ;
 * Get dataset contents information in a format to facilitate code generation.;
 * Column names reflect data statement that uses the value. ;
 *----------------------------------------------------------------------------;
 proc sql noprint;
 select cats('(label=',quote(trim(memlabel),"'"),')') into :memlabel trimmed from dictionary.tables where libname="SASHELP" and memna
 me="CLASS" and not missing(memlabel) ;
 create table _ds2post_ as select varnum , nliteral(name) as name length=66 , substrn(informat,1,findc(informat,' .',-49,'kd')) as in
 f length=32 , case when type='char' then cats(':$',length,'.') when not (lowcase(calculated inf) in ('best','f',' ') and scan(inform
 at,2,'.') = ' ') then ':F.' else ' ' end as input length=8 , case when type='num' and length < 8 then cats(max(3,length)) else ' ' e
 nd as length length=1 , lowcase(format) as format length=49 , lowcase(informat) as informat length=49 , case when missing(label) the
 n ' ' else quote(trim(label),"'") end as label length=300 from dictionary.columns where libname="SASHELP" and memname="CLASS" order 
 by varnum ;
 quit;
 *----------------------------------------------------------------------------;
 * Generate data step code ;
 * - For each statement use value of variable named the same as the statement.;
 * - Only variables that are required in that statement are generated. ;
 * - For LABEL statement use = between name and value instead of space. ;
 * - Wrap statements when lines get too long. ;
 * - Eliminate statements when no variables required that statement. ;
 *----------------------------------------------------------------------------;
 filename _code_ temp;
 data _null_;
 file _code_ column=cc ;
 set _ds2post_ (obs=1) ;
 put "data work.class (label='Student Data');" ;
 put @3 "infile datalines dsd dlm='|' truncover;" ;
 length statement $10 string $370 ;
 do statement='input','length','format','informat','label';
 call missing(any,anysplit);
 put @3 statement @ ;
 do p=1 to nobs ;
 set _ds2post_ point=p nobs=nobs ;
 string=vvaluex(statement);
 if statement='input' or not missing(string) then do;
 any=1;
 string=catx(ifc(statement='label','=',' '),name,string);
 if 72<(cc+length(string)) then do;
 anysplit=1;
 put / @5 @ ;
 end;
 put string @ ;
 end;
 end;
 if anysplit then put / @3 @ ;
 if not any then put @1 10*' ' @1 @ ;
 else put ';' ;
 end;
 put 'datalines4;' ;
 run;
 *----------------------------------------------------------------------------;
 * Generate data lines ;
 *----------------------------------------------------------------------------;
 data _null_;
 file _code_ mod dsd dlm='|';
 if _n_ > 20 then stop;
 set sashelp.class ;
 format _numeric_ best32. _character_ ;
 put (_all_) (+0) ;
 run;
 data _null_;
 file _code_ mod ;
 put ';;;;';
 run;
 *----------------------------------------------------------------------------;
 * Copy generated code to target file name and remove temporary file. ;
 *----------------------------------------------------------------------------;
 data _null_ ;
 infile _code_;
 file log ;
 input;
 put _infile_;
 run;
 filename _code_ ;
 *----------------------------------------------------------------------------;
 * Remove generated metadata. ;
 *----------------------------------------------------------------------------;
 proc delete data=_ds2post_;
 run;
 NOTE: 75 records were read from the infile MPRINT.
       The minimum record length was 4.
       The maximum record length was 671.
 NOTE: DATA statement used (Total process time):
       real time           0.00 seconds
       cpu time            0.00 seconds

Notice the long SQL statement makes a line that is 671 bytes long.

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

Register now!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 3 replies
  • 571 views
  • 7 likes
  • 3 in conversation