My prior post isn't entirely correct. For instance, you do not need the %STR around the regular expression. And, there is a difference in behavior in macro between SAS 9.2 and earlier versions of SAS.
Given that I'm the world's worst macro programmer :-), I had a side chat with the developer for macro and Toby to educate me on what's happening with this seemingly simple example. Here is a better analysis of this situation:
(1) The original code shouldn't put single quotes around the regular expression because macro passes the single quotes to PRXCHANGE, which causes a PRXCHANGE error.
[pre]
%put New String: %sysfunc(prxchange('s/ old / NEWER /oi',-1,' new and old '));
[/pre]
Should be:
[pre]
%put New String: %sysfunc(prxchange(s/ old / NEWER /oi,-1,' new and old '));
[/pre]
(2) On SAS 9.1.3, this code causes an error. On SAS 9.2, this code works fine.
In SAS 9.1.3, the macro processor sees PRXCHANGE could have a numeric or character first argument and it sees the / in the first argument, so it attempts to evaluate the first argument as a numeric expression. This results in an error, an error is output to the log, and a zero length string is passed to PRXCHANGE. PRXCHANGE then outputs an error because an invalid pattern was passed to it.
In SAS 9.2, the macro processor was modified such that if the numeric evaluation fails, it assumes the value must be a character value and the character value is passed to PRXCHANGE. At this point, folks with SAS 9.2 are happy.
What should folks with SAS 9.1.3 do?
I see two solutions:
(2a) Change the regular expression delimiter from / to a non-arithmetic character, like !.
[pre]
%put New String: %sysfunc(prxchange(s! old ! NEWER !oi,-1,' new and old '));
[/pre]
(2b) Have a three statement program that uses PRXPARSE and PRXFREE.
[pre]
%let re = %sysfunc(prxparse(s/ old / NEWER /oi));
%put New String: %sysfunc(prxchange(&re,-1,' new and old '));
%syscall prxfree(re);
[/pre]
This solution works because PRXPARSE only accepts a character argument, so no numeric evaluation is attempted.
(3) The original code has single quotes around the string to be modified. If the result shouldn't have single quotes, the %STR macro function can be used to preserve leading and trailing blanks.
[pre]
%put New String: %sysfunc(prxchange(s! old ! NEWER !oi,-1,%str( new and old )));
[/pre]
Does this make sense?
Jason