Read dates when its in quotes - sas

How to read the dates with quotes. I tried without quotes, its working fine.
How to chance the sysfunc according to it.
%let date='2017-01-01';
%let et=%sysfunc(intnx(month,%sysfunc(inputn(&date.,yymmdd10.)),2,s),yymmn6.);
%put &et.;

Use dequote to remove the quotation marks:
%let date='2017-01-01';
%let et=%sysfunc(intnx(month,%sysfunc(inputn(%sysfunc(dequote(&date.)),yymmdd10.)),2,s),yymmn6.);
%put &et.;

Related

Unexpected parsing of SAS macro function

I want to use catx() in %sysfunc(), test code like this:
%let newtext=%sysfunc(catx(%str(, ),%str(grade>80),test text));
%put &=newtext;
%let newtext=%sysfunc(catx(%str(, ),%str(grade<80),test text));
%put &=newtext;
However, SAS take %str(grade>80) as an expression and just resolve it as 1. The result of above code is
NEWTEXT=1, test text
NEWTEXT=0, test text
I want SAS just return the RAW TEXT, that is:
NEWTEXT=grade>80, test text
NEWTEXT=grade<80, test text
How to avoid this kind of unexpected parsing while using %sysfunc() or %qsysfunc()?
Use literal concatenation in macro
%let newtext=grade>80,test text;
Use catx in DATA Step
newtext = catx(',', 'grade>80', 'test text');
Do not use %SYSFUNC() with data step functions like CATX() that allow arguments to be either numbers or strings. That causes %SYSFUNC() to have to make a guess about what type of value the text you are passing it represents so it can tell the data step function what type of arguments it is receiving.
To concatenate in macro code just expand the values next to each other.
%let newtext=grade>80,test text;
To handle the optional insertion of the delimiter that CATX() does add your own macro logic.
%macro catx(dlm,left,right);
%if %length(&left) and %length(&right) %then &left.&dlm.&right ;
%else &left.&right ;
%mend;

SAS macro variable containing two macro variables is not resolved

I have two macro variables, path and file, both of them contains special characters. I use %str for both. Then combine them as another macro variable, direct.
when I use &direct in filename pipe statement, it is not resolved.
Can anyone tell me what it is wrong?
I have tried double quote or %sysfunc(cats()). not work either.
code as:
%let path=%str(B:\Enrollment Report\Fall 18\18F Enroll- MASTER\);
%let file=%str(18F Enroll as *.xlsx);
%let direct=%sysfunc(cats(&path, &file));
%put &direct;
filename dirlist pipe 'dir "&direct" /b';
NOTE: The infile DIRLIST is:
Unnamed Pipe Access Device,
PROCESS=dir "&direct" /b,RECFM=V,LRECL=200
Macro triggers are not resolved inside of single quotes. One easy way is to use double quote characters instead, remember to double any embedded double quote characters.
Note there is no need to use CATS() in macro code. Or add %STR() macro quoting to values that don't need quoting.
%let path=B:\Enrollment Report\Fall 18\18F Enroll- MASTER;
%let file=18F Enroll as *.xlsx;
%let direct=&path\&file;
filename dirlist pipe "dir ""&direct"" /b";

SAS: Delete missing items in a macro variable

I have a macro variable called list1, which gives:
%put &list1.;
A,B,C,D,,,G,,I,,
I need to delete those items which are missing i.e empty between the commas. The final output should be like A,B,C,D,G,I. Is it possible? Trim function does not seem to work here. I'm new to SAS so any help will be appreciated here. Thanks.
%let a= A,B,C,D,,,G,,I,,;
data c;
val = tranwrd(trim(compbl(tranwrd("&a",","," "))), " ",",");
call symput('b',val);
run;
%put &b;
This result of A,B,C,D,G,I
Just for fun - pure macro regex version:
%let a= A,B,C,D,,,G,,I,,;
%let regex1 = %sysfunc(prxparse(%str(s/,+/,/)));
%let b=%sysfunc(prxchange(&regex1,-1,%quote(&a)));
%let regex2 = %sysfunc(prxparse(%str(s/,$//)));
%let b=%sysfunc(prxchange(&regex2,-1,%quote(&b)));
%put b= &b;
You can skip the second regex if you never have to deal with trailing commas at the end of your input.
You could convert the commas to spaces and use COMPBL() to collapse the multiple spaces. Then convert the spaces back into commas. In case you have any spaces just swap the comma and the space characters.
%let temp=%sysfunc(translate(%superq(list1),%str( ,),%str(, )));
%let temp=%sysfunc(compbl(%superq(temp)));
%let list2=%sysfunc(translate(%superq(temp),%str( ,),%str(, )));
PS You don't normally want to use comma as the delimiter in macro variables. It makes it difficult to pass the value to other macros or functions since comma is used to separate argument values. Hence all of the macro quoting functions in this code. For variable lists you would normally want a space delimited list where multiple adjacent spaces wouldn't matter. For other types of lists you would normally want another delimiter like | or ^.

transform guid to string for sas put statement

The following code should print a guid to the log:
%let test = %sysfunc(uuidgen());
data _null_;
put &test.;
run;
For some reasons the put line fails. Any ideas? Thanks!
You forgot the %:
%put &test.;
The put statement in the datastep prints either variables or a string literals.
In your case you have a value within a macro variable that you would like the put statement to interpret as a string literal. You can do this by wrapping it in quotes:
data _null_;
put "&test";
run;
If you want to use the macro %put statement. You can just replace the whole datastep with:
%put &test;

Multiple search and replace within a string through regular expression in SAS

I have following macro variable:
%let text = abc\pqr{work};
I need to replace \ with \\, { with \{ and } with \} by regular expression.
The code I tried gives error.
%let text = abc\pqr{work};
data _null_;
var=prxchange('s/\\/\\\\/|s/\{/ \\\{/|s/\}/ \\\}/',-1,"&text");
put var;
run;
Also, if the text is "BOLD\ITALIC\ITALICBOLD\BOLDITALIC\B\I\IB\BI", I need to convert it to "\b\i\ib\bi\b\i\ib\bi".
For your first problem, you should be separating each pattern into a separate PRXCHANGE. I don't think PRXCHANGE allows OR operand in it. If run this code, it will work for you:
%let text = abc\pqr{work};
data _null_;
var=prxchange("s/\\/\\\\/",-1,"&text");
var=prxchange("s/\{/\\\{/",-1,var);
var=prxchange("s/\}/\\\}/",-1,var);
put var;
run;
The same principle applies to your second query:
%let text = BOLD\ITALIC\ITALICBOLD\BOLDITALIC\B\I\IB\BI;
data _null_;
var=prxchange("s/BOLD/b/",-1,"&text");
var=prxchange("s/ITALIC/i/",-1,var);
var=lowcase(var);
put var;
run;
Regads,
Vasilij