DATA Step, Macro, Functions and more

Replace a text string when it occurs more than once

Reply
Occasional Contributor
Posts: 9

Replace a text string when it occurs more than once

Dear all,

I have the following problem:
I use the macro described here: http://www2.sas.com/proceedings/sugi24/Coders/p086-24.pdf.

Code:
%macro replace (dataset = , chkvar = , search = , replace =,
newvar = );
data &dataset (drop = textpos) newvars;
length &newvar $ 200;
set &dataset;
textpos = index(upcase(&chkvar), upcase("&search"));
oldvar = &chkvar;
if textpos ne 0 then
do;
if textpos ne 1 then
&newvar = substr(&chkvar, 1, (textpos - 1)) ||"&replace"||substr(&chkvar, (textpos+length("&search")));
else &newvar = "&replace"||
substr(&chkvar, (textpos + length("&search")));
output newvars;
end;
else &newvar = &chkvar;
output &dataset;
run;
proc print data = newvars;
title “SEARCH FOR ‘&search’ AND REPLACE WITH ‘&replace’”;
var oldvar &newvar;
run;
%mend replace;


This macro replaces a specified string in a cell. The problem is, that it only replaces the first specified string that appears in a cell, when the specified string occurs more than once, the macro does not replace all specified string appearing in the cell but only the first one. How could the macro be fixed in order to replace the specified string as often as the specified string occurs in the cell?

Thanks a lot for your help.

Valentin
Super Contributor
Super Contributor
Posts: 365

Re: Replace a text string when it occurs more than once

Hello Valentin,

One of the possible solutions is to loop of this macro making a slight change in its code, namely output testpos as a macro variable, and loop untill testpos=0 like this:
[pre]
%macro replace (dataset = , chkvar = , search = , replace =,
newvar = );
%global tp;
data &dataset (drop = textpos) newvars;
length &newvar $ 200;
set &dataset;
textpos = index(upcase(&chkvar), upcase("&search"));
CALL SYMPUTX('tp',textpos);
oldvar = &chkvar;
if textpos ne 0 then
do;
if textpos ne 1 then
&newvar = substr(&chkvar, 1, (textpos - 1)) ||"&replace"||substr(&chkvar, (textpos+length("&search")));
else &newvar = "&replace"||
substr(&chkvar, (textpos + length("&search")));
output newvars;
end;
else &newvar = &chkvar;
output &dataset;
run;
proc print data = newvars;
title “SEARCH FOR ‘&search’ AND REPLACE WITH ‘&replace’”;
var oldvar &newvar;
run;
%mend replace;
%macro a;
%global tp;
%do %until (&tp = 0);
%replace (dataset = a, chkvar = a, search = dg, replace = yy, newvar =a );
%end;
%mend a;
data a;
a="asdgdfgdg";
b="dg";
run;
%a
[/pre]
Sincerely,
SPR
Regular Contributor
Posts: 171

Re: Replace a text string when it occurs more than once

Maybe I’ve misunderstood your objective, but wouldn’t it be a lot easier to just use the TRANWRD function?
Regular Contributor
Posts: 241

Re: Replace a text string when it occurs more than once

Here is one way. hth.

/* test data */
data one;
   old = "asdgdfgdg";
run;

/* create a new var replacing dg with YY in old */
data two;
   set one;
   length new $9;
   new = prxchange("s|dg|YY|", -1, old);
run;

/* check */
proc print data=two;
run;
/* on lst
   Obs   old          new
   1     asdgdfgdg    asYYdfgYY
*/

PROC Star
Posts: 7,360

Re: Replace a text string when it occurs more than once

I like Chang's suggested code and, if you want, it would be simple to wrap it in a macro. E.g., the following uses the same structure (mostly) of the original:
[pre]
%macro replace (dataset = , search = , replace =, variable =, newlength = );
data &dataset. (drop = oldvar);
set &dataset. (rename=(&variable.=oldvar));
length &variable $&newlength.;
&variable. = prxchange("s|&search.|&replace.|", -1, oldvar);
run;
%mend replace;
data have;
informat aetext $50.;
input PTID AETEXT &;
cards;
110 ABD. CRAMPING
160 INTRA-ABD. ABSCESS ABD.
190 (L) ABD. PAIN
220 FOOT ULCER (L) FOOT
230 ABD. PAIN
360 (L) ELBOW CONTUSION
440 PAIN (L) KNEE
520 ACNE
520 TINGLING (L) FOOT
530 ASCITES ABD.
;
run;

%replace (dataset = have,
search = ABD.,
replace = ABDOMINAL,
variable = aetext,
newlength = 50)
[/pre]
HTH,
Art

> Here is one way. hth.

>

>    
> style="color:#008000;font-family:Courier
> New;font-size:10pt;">/* test data */ > pan>

>    
> style="color:#000080;font-family:Courier
> New;font-size:10pt;">data

> style="font-family:Courier
> New;font-size:10pt;"> one;


>      old
>  = 

> style="color:#800080;font-family:Courier
> New;font-size:10pt;">"asdgdfgdg"

> style="font-family:Courier
> New;font-size:10pt;">;


>    
> style="color:#000080;font-family:Courier
> New;font-size:10pt;">run

> style="font-family:Courier
> New;font-size:10pt;">;


>  

>    
> style="color:#008000;font-family:Courier
> New;font-size:10pt;">/* create a new&nb
> sp;var replacing dg with YY i
> n old */


>    
> style="color:#000080;font-family:Courier
> New;font-size:10pt;">data

> style="font-family:Courier
> New;font-size:10pt;"> two;


>       > pan>set
> style="font-family:Courier
> New;font-size:10pt;"> one;


>       > pan>length
> style="font-family:Courier
> New;font-size:10pt;"> new $

> style="color:#008080;font-family:Courier
> New;font-size:10pt;">9

> style="font-family:Courier
> New;font-size:10pt;">;


>      new
>  = prxchange(

> style="color:#800080;font-family:Courier
> New;font-size:10pt;">"s|dg|YY|"

> style="font-family:Courier
> New;font-size:10pt;">, -

> style="color:#008080;font-family:Courier
> New;font-size:10pt;">1

> style="font-family:Courier
> New;font-size:10pt;">, old);


>    
> style="color:#000080;font-family:Courier
> New;font-size:10pt;">run

> style="font-family:Courier
> New;font-size:10pt;">;


>  

>    
> style="color:#008000;font-family:Courier
> New;font-size:10pt;">/* check */


> />
>    
> style="color:#000080;font-family:Courier
> New;font-size:10pt;">proc

> style="font-family:Courier
> New;font-size:10pt;"> 

> style="color:#000080;font-family:Courier
> New;font-size:10pt;">print

> style="font-family:Courier
> New;font-size:10pt;"> 

> style="color:#0000FF;font-family:Courier
> New;font-size:10pt;">data

> style="font-family:Courier
> New;font-size:10pt;">=two;


>    
> style="color:#000080;font-family:Courier
> New;font-size:10pt;">run

> style="font-family:Courier
> New;font-size:10pt;">;


>    
> style="color:#008000;font-family:Courier
> New;font-size:10pt;">/* on lst


> />
>    Obs  
>      old   &nb
> sp;      new


> />
>     1 &n
> bsp;   asdgdfgdg    
> ;asYYdfgYY


>    */
Ask a Question
Discussion stats
  • 4 replies
  • 203 views
  • 0 likes
  • 5 in conversation