In SAS, outside of a data step, what is the best way to replace a character in a macro variable with a blank? - sas

In SAS, outside of a data step, what is the best way to replace a character in a macro variable with a blank?
It seems that TRANSLATE would be a good function to use. However when using %SYSFUNC with this function, the parameters are not surrounded with quotes. How do you indicate a blank should be used as replacement?

The %str( ) (with a blank between the parens) can be used to indicate a blank for this parameter. Also be careful with TRANSLATE...the 2nd param is the replacement char...however in TRANWRD it is reversed.
%macro test ;
%let original= translate_this_var ;
%let replaceWithThis= %str( ) ;
%let findThis= _ ;
%let translated= %sysfunc(translate(&original, &replaceWithThis, &findThis)) ;
%put Original: &original ***** TRANSLATEd: &translated ;
%mend ;
%test;
%macro test2 ;
%let original= translate_this_var ;
%let replaceWithThis= %str( ) ;
%let findThis= _ ;
%let tranwrded= %sysfunc(tranwrd(&original, &findThis, &replaceWithThis)) ;
%put Original: &original ***** TRANWRDed: &tranwrded ;
%mend ;
%test2

There are no quotes in macro language. The only quotes characters that are in use are the & , % etc. to indicate that the text should be interpreted as a macro "operator". A blank is represented by %str( ) as indicated above in Carolina's post.

you can use perl reg ex instead, like:
%put ***%sysfunc(prxchange(s/x/ /, -1, abxcdxxf))***;
/* on log
***ab cd f***
*/

Related

SAS BASE method %index where second parametr equals ','

I have some code:
%if %index(&CompanyName,&) %then %do;
%let error_code = 4;
%let error_msg = &ERR_CONT_SYMB;
%return;
%end;
When a company name has an & symbol, an error should be thrown.
If replaced with another character such as % $ . then everything works the same.
I need to replace the & with a comma, but that's not possible.
No quotes help (, ',' ",")

SAS mainframe replace 20..99 to 200099

In my the sas mainframe code how to replace . with 0?
data newlic;
INPUT #1 LICNO $10.;
DATALINES;
203....412
...3300421
9955..032.
;
RUN;
PROC PRINT DATA = NEWLIC;
RUN;
DATA MYDATA;
SET NEWLIC;
ARRAY A(*) _NUMERIC_;
DO I=1 TO DIM(A);
IF A(I) = . THEN A(I) = 0;
END;
DROP I;
RUN;
PROC PRINT DATA = MYDATA;
RUN;
my required output
2030000412
0003300421
9955000320
the requirement is to replace '.' to 0
Use a regular expression to replace all non-alphanumeric characters with a 0:
s/[^0-9a-zA-Z]/0/
You can implement regex replacements in SAS with prxchange().
data mydata;
set newlic;
licno = prxchange('s/[^0-9a-zA-Z]/0/', -1, licno);
run;
You can use the TRANSLATE() function to replace unwanted characters with '0'. You can use the COMPRESS() function with d modifier to find any non-digit characters that exist in the value.
fixed=translate(licno,repeat('0',255),compress(licno,,'d'));
Results:
Obs LICNO fixed
1 1234567890 1234567890
2 ABC 9 0000000009
3 203....412 2030000412
4 ...3300421 0003300421
5 9955..032. 9955000320
6 123 1230000000
You can use the regular expression pattern metacharacter \D to locate non-digit characters and replace them with 0 in a use of PRXCHANGE().
From the complete list in the documentation
\d matches a digit character that is equivalent to [0−9].
\D matches any character that is not a digit.
Example:
data have; input
licno $char10.; datalines;
1234567890
ABC 9
203....412
...3300421
9955..032.
123
;
data want;
set have;
fixed = prxchange('s/\D/0/', -1, licno);
run;

SAS Retain not working for 1 string variable

The below code doesn't seem to be working for the variable all_s when there is more than 1 record with the same urn. Var1,2,3 work fine but that one doesn't and I cant figure out why. I am trying to have all_s equal to single_var1,2,3 concatenated with no spaces if it's first.urn but I want it to be
all_s = all_s + ',' + single_var1 + single_var2 + single_var3
when it's not the first instance of that urn.
data dataset_2;
set dataset_1;
by URN;
retain count var1 var2 var3 all_s;
format var1 $40. var2 $40. var3 $40. all_s $50.;
if first.urn then do;
count=0;
var1 = ' ';
var2 = ' ';
var3 = ' ';
all_s = ' ';
end;
var1 = catx(',',var1,single_var1);
var2 = catx(',',var2,single_var2);
var3 = catx(',',var3,single_var3);
all_s = cat(all_s,',',single_var1,single_var2,single_var3);
count = count+1;
if first.urn then do;
all_s = cat(single_var1,single_var2,single_var3);
end;
run;
all_s is not large enough to contain the concatenation if the total length of the var1-var3 values within the group exceeds $50. Such a scenario seems likely with var1-var3 being $40.
I recommend using the length function to specify variable lengths. format will create a variable of a certain length as a side effect.
catx removes blank arguments from the concatenation, so if you want spaces in the concatenation when you have blank single_varN you won't be able to use catx
A requirement that specifies a concatenation such that non-blank values are stripped and blank values are a single blank will likely have to fall back to the old school trim(left(… approach
Sample code
data have;
length group 8 v1-v3 $5;
input group (v1-v3) (&);
datalines;
1 111 222 333
1 . 444 555
1 . . 666
1 . . .
1 777 888 999
2 . . .
2 . b c
2 x . z
run;
data want(keep=group vlist: all_list);
length group 8 vlist1-vlist3 $40 all_list $50;
length comma1-comma3 comma $2;
do until (last.group);
set have;
by group;
vlist1 = trim(vlist1)||trim(comma1)||trim(left(v1));
vlist2 = trim(vlist2)||trim(comma2)||trim(left(v2));
vlist3 = trim(vlist3)||trim(comma3)||trim(left(v3));
comma1 = ifc(missing(v1), ' ,', ',');
comma2 = ifc(missing(v2), ' ,', ',');
comma3 = ifc(missing(v3), ' ,', ',');
all_list =
trim(all_list)
|| trim(comma)
|| trim(left(v1))
|| ','
|| trim(left(v2))
|| ','
|| trim(left(v3))
;
comma = ifc(missing(v3),' ,',',');
end;
run;
Reference
SAS has operators and multiple functions for string concatenation
|| concatenate
cat concatenate
catt concatenate, trimming (remove trailing spaces) of each argument
cats concatenate, stripping (remove leading and trailing spaces) of each argument
catx concatenate, stripping each argument and delimiting
catq concatenate with delimiter and quote arguments containing the delimiter
From SAS 9.2 documentation
Comparisons
The results of the CAT, CATS, CATT, and CATX functions are usually equivalent to results that are produced by certain combinations of the concatenation operator (||) and the TRIM and LEFT functions. However, the default length for the CAT, CATS, CATT, and CATX functions is different from the length that is obtained when you use the concatenation operator. For more information, see Length of Returned Variable.
Note: In the case of variables that have missing values, the concatenation produces different results. See Concatenating Strings That Have Missing Values.
Some example data would be helpful, but I'm going to give it a shot and ask you to try
all_s = cat(strip(All_s),',',single_var1,single_var2,single_var3);

how to pass a string to a macro sas without special char

I wrote this macro in sas to have some information about some files :
%macro info_1(cmd);
filename dirList pipe &cmd.;
data work.dirList;
infile dirList length=reclen;
input file $varying200. reclen;
permission=scan(file,1,"");
if input(scan(file,2,""), 8.)=1;
user=scan(file,3,"");
group=scan(file,4,"");
file_size_KB=round(input(scan(file,5,""), 8.)/1024,1);
file_size_MB=round(input(scan(file,5,""), 8.)/1024/1024,1);
modified_time=input(catx(" ",scan(file,6," "),scan(file,7,"")),anydtdtm.);
date_mod = datepart(modified_time);
time_zone=scan(file,8,"");
file_name=scan(file,-1,"");
format modified_time datetime19.;
format file_size_MB comma9.;
format date_mod date9.;
run;
%mend info_1;
then i declare this macro variable:
%let cmd = ls --full-time;
%let sep1= %quote( );
%let path = /data/projects/flat_file/meteo ;
%let file = *.json ;
%let sep2 = %quote(/) ;
%let fullpath = &cmd.&sep1.&path.&sep2.&file;
Then i try to execute the macro :
%info_1(&fullpath.);
And i see a strange thing. I post a image because it is impossible to describe it. I guess that there are special chars.
How to fix that thing?
Inside your macro I believe you just need to add quotes around this line:
filename dirList pipe &cmd.;
Right now after the macro resolution is happening it is treating it like:
filename dirList pipe ls --full-time;
... which is treating the ls part onwards like parameters to the filename statement. When fixed the code should appear as:
filename dirList pipe "&cmd";
Which will then be resolved as:
filename dirList pipe "ls --full-time";

Regular Expression dot in SAS

I'm new in this field, and try to use prxmatch and rxmatch to match some strings.
The pattern is a., which matches a string with more than 2 characters and a isn't the last one.
I run prxmatch('/a./', 'a') and rxmatch('/a./', 'a'), the result should be 0. But the system returns me 1.
So how can I get 0 in this case?
If you write a MCVE for this, you do get no match.
data test;
x='a';
rc=prxmatch('~a.~',x);
put x= rc=;
run;
However, if x is not length 1, it will match!
data test;
length x $5;
x='a';
rc=prxmatch('~a.~',x);
put x= rc=;
run;
Why?
Because in SAS, strings are not varchar, they are char. They have spaces padding the rest of the string out to its full length. So you would need to do either
data test;
length x $5;
x='a';
rc=prxmatch('~a[^ ]~',x);
put x= rc=;
run;
or, better,
data test;
length x $5;
x='a';
rc=prxmatch('~a.~',trim(x));
put x= rc=;
run;
(Note, I use ~ for my regex delimiter - you're free to use slash, or any other character, for that, it makes no difference.)