transform guid to string for sas put statement - sas

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;

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";

Tranwrd just one letter in SAS

How can i quote just one letter in sas?
%sysfunc(tranwrd(%quote(&string),%quote(T),%quote('Test')));
The Problem is, when the string has a 'T' and 'TR' that both get tranwrd to 'Test'
SAS Macro variables are always character. The arguments to macro functions are always character and generally won't require an extra layer of macro macro quoting, and definitely won't if the arguments are to be as literals.
Did you try this first ?
%let string = STACKOVERFLOW;
%let string_tweaked = %sysfunc(tranwrd(&string),T,Test);
%put NOTE: string_tweaked = &string_tweaked;
Do the macro values contain embedded single quotes ?
%let string = %str(S%'T%'ACKOVERFLOW);
%let string_tweaked = %qsysfunc(tranwrd(&string,'T','Test'));
%put NOTE: string_tweaked = &string_tweaked;
The second code sample is analogous to the following DATA step code (whose scope is different than that of the MACRO environment). DATA step string values are explicitly quoted, with either double quote (") or single quote (')
data _null_;
string = "S'T'ACKOVERFLOW";
string_tweaked = tranwrd(string,"'T'","'Test'");
put "NOTE: " string_tweaked=;
run;

what the last "." after the macro variable mean

Below is the code to create the dataset from exisitng datasets, where end and end8, end7 are macro variables, just wondering why add . at the end of the macro variables?
data tab4a_&end.;
set
mck_tab4a_&end8.
mck_raw.mck_tab4a_&end7.
run;
The dot marks the end of the macro variable. It is often used when macro text is combined with static text, e.g. in a filename, so that SAS knows where the macro variable ends. E.g.:
%let year=2017;
%let filename = &year._accounts.xlsx;
%put &filename;
Produces 2017_accounts.xlsx
Without the first dot, SAS will produce a warning message, because it will be looking for a macro variable called year_accounts. (It can't tell where the macro ends and the text starts).
If there is a space or an end of statement after the macro variable then the dot can be omitted. Including the dot has no effect in this case. Some people think it is good to always include the dot.
It's used to denote the end of a macro variable. This is important when you're mixing macro variables and text.
For example:
%let my_var = TEST;
%let my_var_new = WRONG;
%put &my_var._new;
%put &my_var_new.;
OUTPUT:
58 %let my_var = TEST;
59 %let my_var_new = WRONG;
60 %put &my_var._new;
TEST_new
61 %put &my_var_new.;
WRONG
How does the macro processor know if the macro variable is my_var or my_var_new? The period tells SAS where the macro variable ends.
Including the dot also turns the macro variable green in the editor which helps for reading and debugging code.

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