1
0
mirror of https://github.com/sasjs/core.git synced 2026-01-07 09:30:06 +00:00

fix: adding test and updating documentation

This commit is contained in:
munja
2022-03-03 12:46:00 +00:00
parent fe9a2ed979
commit ccf8f1acc0
2 changed files with 91 additions and 31 deletions

View File

@@ -1,13 +1,15 @@
/** /**
@file @file
@brief Performs a text substitution on a file @brief Performs a text substitution on a file
@details Reads a file in byte by byte, performing text substiution where a @details Performs a find and replace on a file, either in place or to a new
match is found. file. Can be used on files where lines are longer than 32767.
This macro can be used on files where lines are longer than 32767. Works by reading in the file byte by byte, then marking the beginning and end
of each matched string, before finally doing the replace.
If you are running a version of SAS that will allow the io package in LUA, you Full credit for this highly efficient and syntactically satisfying SAS logic
can also use this macro: mp_gsubfile.sas goes to [Bartosz Jabłoński](https://www.linkedin.com/in/yabwon), founder of
the [SAS Packages](https://github.com/yabwon/SAS_PACKAGES) framework.
Usage: Usage:
@@ -27,6 +29,9 @@
list; list;
run; run;
Note - if you are running a version of SAS that will allow the io package in
LUA, you can also use this macro: mp_gsubfile.sas
@param infile The QUOTED path to the file on which to perform the substitution @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 findvar= Macro variable NAME containing the string to search for
@param replacevar= Macro variable NAME containing the replacement string @param replacevar= Macro variable NAME containing the replacement string
@@ -41,6 +46,7 @@
@li mp_gsubfile.test.sas @li mp_gsubfile.test.sas
@version 9.4 @version 9.4
@author Bartosz Jabłoński
@author Allan Bowe @author Allan Bowe
**/ **/
@@ -64,39 +70,37 @@ filename &inref &infile lrecl=1 recfm=n;
data &ds1; data &ds1;
infile &inref; infile &inref;
input x $ 1. @@; input sourcechar $ 1. @@;
format x hex2.; format sourcechar hex2.;
run; run;
data &ds2; data &ds2;
/* set find string to length in bytes to cover trailing spaces */ /* set find string to length in bytes to cover trailing spaces */
length string $ %length(%superq(&findvar)); length string $ %length(%superq(&findvar));
string =symget("&findvar"); string =symget("&findvar");
drop string; drop string;
z =char(string,1); firstchar=char(string,1);
l =lengthm(string); /* <- for trailing bytes */ findlen=lengthm(string); /* <- for trailing bytes */
do _N_ =1 to nobs; do _N_=1 to nobs;
set &ds1 nobs=nobs point=_N_; set &ds1 nobs=nobs point=_N_;
if x =z then do; if sourcechar=firstchar then do;
pos =1; pos=1;
s =0; s=0;
do point =_N_ to min(_N_ + l -1,nobs); do point=_N_ to min(_N_ + findlen -1,nobs);
set &ds1 point=point; set &ds1 point=point;
if x =char(string, pos) then s + 1; if sourcechar=char(string, pos) then s + 1;
else goto _leave_; else goto _leave_;
pos+1; pos+1;
end; end;
_leave_: _leave_:
if s =l then do; if s=findlen then do;
START =_N_; START =_N_;
_N_ =_N_+ s - 1; _N_ =_N_+ s - 1;
STOP =_N_; STOP =_N_;
output; output;
end; end;
else _N_ =_N_+ s;
end; end;
end; end;
stop; stop;
@@ -107,31 +111,22 @@ data &ds1;
declare hash HS(dataset:"&ds2(keep=start)"); declare hash HS(dataset:"&ds2(keep=start)");
HS.defineKey("start"); HS.defineKey("start");
HS.defineDone(); HS.defineDone();
declare hash HE(dataset:"&ds2(keep=stop)"); declare hash HE(dataset:"&ds2(keep=stop)");
HE.defineKey("stop"); HE.defineKey("stop");
HE.defineDone(); HE.defineDone();
do until(eof); do until(eof);
set &ds1 end=eof curobs =n; set &ds1 end=eof curobs =n;
start = ^HS.check(key:n);
start=0; stop = ^HE.check(key:n);
stop=0;
if 0 =HS.check(key:n) then start =1;
if 0 =HE.check(key:n) then stop =1;
length strt $ 1; length strt $ 1;
strt =put(start,best. -L); strt =put(start,best. -L);
retain out 1; retain out 1;
if out then output; if out then output;
if start then out=0; if start then out=0;
if stop then out=1; if stop then out=1;
end; end;
stop; stop;
keep sourcechar strt;
keep x strt;
run; run;
filename &outref &outfile recfm=n; filename &outref &outfile recfm=n;
@@ -143,7 +138,7 @@ data _null_;
do until(eof); do until(eof);
set &ds1 end=eof; set &ds1 end=eof;
if strt ="1" then put replace char.; if strt ="1" then put replace char.;
else put x char1.; else put sourcechar char1.;
end; end;
stop; stop;
run; run;

View File

@@ -0,0 +1,65 @@
/**
@file
@brief Testing mp_replace.sas macro
<h4> SAS Macros </h4>
@li mp_replace.sas
@li mp_assert.sas
@li mp_assertscope.sas
**/
%let test1="&sasjswork/file.txt";
%let str=replace/me;
%let rep=with/this;
data _null_;
file &test1;
put 'blahblah';
put "blahblah&str.blah";
put 'blahblahblah';
run;
%mp_assertscope(SNAPSHOT)
%mp_replace(&test1, findvar=str, replacevar=rep)
%mp_assertscope(COMPARE)
data _null_;
infile &test1;
input;
if _n_=2 then call symputx('test1result',_infile_);
run;
%mp_assert(
iftrue=("&test1result" = "blahblah&rep.blah"),
desc=Checking first replace,
outds=work.test_results
)
%let test2="&sasjswork/file2.txt";
%let str=%str(replacewith trailing spaces );
%let rep=%str( with more spaces );
data _null_;
file &test2;
put 'blahblah';
put "blahblah&str.blah&str. replace &str.X";
put "blahbreplacewith&str.spacesahblah";
run;
%mp_replace(&test2, findvar=str, replacevar=rep)
data _null_;
infile &test2;
input;
if _n_=2 then call symputx('test2resulta',_infile_);
if _n_=3 then call symputx('test2resultb',_infile_);
run;
%mp_assert(
iftrue=("&test2resulta" = "blahblah&rep.blah&rep. replace &rep.X"),
desc=Checking second replace 2nd row,
outds=work.test_results
)
%mp_assert(
iftrue=("&test2resultb" = "blahbreplacewith&rep.spacesahblah"),
desc=Checking second replace 3rd row,
outds=work.test_results
)