diff --git a/base/mp_replace.sas b/base/mp_replace.sas
index 92825a2..d20e68e 100644
--- a/base/mp_replace.sas
+++ b/base/mp_replace.sas
@@ -11,29 +11,31 @@
Usage:
- %let file=%sysfunc(pathname(work))/file.txt;
+ %let file="%sysfunc(pathname(work))/file.txt";
%let str=replace/me;
%let rep=with/this;
data _null_;
- file "&file";
+ file &file;
put 'blahblah';
put "blahblah&str.blah";
put 'blahblahblah';
run;
- %mp_replace(file=&file, patternvar=str, replacevar=rep)
+ %mp_replace(&file, findvar=str, replacevar=rep)
data _null_;
- infile "&file";
+ infile &file;
input;
list;
run;
- @param file= (0) The file to perform the substitution on
- @param patternvar= Macro variable NAME containing the string to search for
+ @param infile The QUOTED path to the file on which to perform the substitution
+ @param findvar= Macro variable NAME containing the string to search for
@param replacevar= Macro variable NAME containing the replacement string
- @param outfile= (mp_rplce) The output fileref to contain the adjusted file.
+ @param outfile= (0) Optional QUOTED path to an the adjusted output file (to
+ avoid overwriting the first file).
SAS Macros
- @li ml_gsubfile.sas
+ @li mf_getuniquefileref.sas
+ @li mf_getuniquename.sas
Related Macros
@li mp_gsubfile.test.sas
@@ -42,12 +44,111 @@
@author Allan Bowe
**/
-%macro mp_replace(file=0,
- patternvar=,
+%macro mp_replace(infile,
+ findvar=,
replacevar=,
- outref=mp_rplce
+ outfile=0
)/*/STORE SOURCE*/;
- %ml_gsubfile()
+%local inref dttm ds1;
+%let inref=%mf_getuniquefileref();
+%let outref=%mf_getuniquefileref();
+%if &outfile=0 %then %let outfile=&infile;
+%let ds1=%mf_getuniquename(prefix=allchars);
+%let ds2=%mf_getuniquename(prefix=startmark);
+
+/* START */
+%let dttm=%sysfunc(datetime());
+
+filename &inref &infile lrecl=1 recfm=n;
+
+data &ds1;
+ infile &inref;
+ input x $ 1. @@;
+ format x hex2.;
+run;
+
+data &ds2;
+
+ /* set find string to length in bytes to cover trailing spaces */
+ length string $ %length(%superq(&findvar));
+ string =symget("&findvar");
+ drop string;
+
+ z =char(string,1);
+ l =lengthm(string); /* <- for trailing bytes */
+
+ do _N_ =1 to nobs;
+ set &ds1 nobs=nobs point=_N_;
+ if x =z then do;
+ pos =1;
+ s =0;
+ do point =_N_ to min(_N_ + l -1,nobs);
+ set &ds1 point=point;
+ if x =char(string, pos) then s + 1;
+ else goto _leave_;
+ pos+1;
+ end;
+ _leave_:
+ if s =l then do;
+ START =_N_;
+ _N_ =_N_+ s - 1;
+ STOP =_N_;
+ output;
+ end;
+ else _N_ =_N_+ s;
+ end;
+ end;
+ stop;
+ keep START STOP;
+run;
+
+data &ds1;
+ declare hash HS(dataset:"&ds2(keep=start)");
+ HS.defineKey("start");
+ HS.defineDone();
+
+ declare hash HE(dataset:"&ds2(keep=stop)");
+ HE.defineKey("stop");
+ HE.defineDone();
+
+ do until(eof);
+ set &ds1 end=eof curobs =n;
+
+ start=0;
+ stop=0;
+ if 0 =HS.check(key:n) then start =1;
+ if 0 =HE.check(key:n) then stop =1;
+
+ length strt $ 1;
+ strt =put(start,best. -L);
+
+ retain out 1;
+ if out then output;
+ if start then out=0;
+ if stop then out=1;
+ end;
+
+ stop;
+
+ keep x strt;
+run;
+
+filename &outref &outfile recfm=n;
+
+data _null_;
+ length replace $ %length(%superq(&replacevar));
+ replace=symget("&replacevar");
+ file &outref;
+ do until(eof);
+ set &ds1 end=eof;
+ if strt ="1" then put replace char.;
+ else put x char1.;
+ end;
+ stop;
+run;
+
+/* END */
+%put &sysmacroname took %sysevalf(%sysfunc(datetime())-&dttm) seconds to run;
%mend mp_replace;