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:
@@ -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;
|
||||||
|
|||||||
65
tests/crossplatform/mp_replace.test.sas
Normal file
65
tests/crossplatform/mp_replace.test.sas
Normal 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
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user