SAS macro variable containing two macro variables is not resolved - sas

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

Related

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.

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;

SAS: Break up long string in code

I find it good practice to restrict my code to within 80 characters per line. Since SAS ignores white space, this usually isn't a problem. However, I occasionally need to refer to some string which is excessively long.
For example,
filename infile "B:\This\file\path\is\really\long\but\there\is\nothing\I\can\do\about\it\because\it\is\on\a\shared\network\drive\and\I\am\stuck\with\whatever\organization\or\lack\thereof\exists\for\directory\hierarchies\filename.txt";
I can think of two solutions:
1) Insert a carriage return. This however makes the code look quite messy and may unwittingly introduce invisible characters (i.e \r\n) into the string.
filename infile "B:\This\file\path\is\really\long\but\there\is\nothing\
I\can\do\about\it\because\it\is\on\a\shared\network\drive\and\I\am\stuck\
with\whatever\organization\or\lack\thereof\exists\for\directory\hierarchies\
filename.txt";
2) Use macro variables to break the string into several parts.
%let part1 = B:\This\file\path\is\really\long\but\there\is\nothing\;
%let part2 = I\can\do\about\it\because\it\is\on\a\shared\network\drive\and\I\am\stuck\;
%let part3 = with\whatever\organization\or\lack\thereof\exists\for\directory\hierarchies\;
%let part4 = filename.txt;
filename infile "&part1.&part2.&part3.&part4.";
%let path = %sysfunc(pathname(infile));
%put &path;
Ideally, I would like something which allows me to follow the indentation scheme of the rest of the code.
filename infile "B:\This\file\path\is\really\long\but\there\is\nothing\
I\can\do\about\it\because\it\is\on\a\shared\network\drive\and\I\am\stuck\
with\whatever\organization\or\lack\thereof\exists\for\directory\hierarchies\
filename.txt";
A possible solution, at least within the context of this example, would be to bypass a declaration altogether and prompt the use for the input file. This does not appear easy to implement, however.
For this type of situation where the string needs to be used as one token then splitting it into separate macro variables is the best approach.
%let basedir=b:\Main Folder;
%let project=This project\has\many\parts;
%let fname=filename.txt ;
...
infile "&basedir/&project/&fname" ;
Note that SAS is happy to convert your directory delimiters between Unix (/) and Windows (\) style automatically for you.
You could also take advantage of using a fileref to point to a starting point in your directory tree.
filename basedir "&basedir";
...
infile basedir("&project/&fname");
You could also store the path in a text file or dataset and use that to generate the path into a macro variable.
data _null_;
infile 'parameter_file.txt' ;
input filename :$256. ;
call symputx('filename',filename);
run;
...
infile "&filename" ;
Another variation on using macro variable is to use multiple %LET statements to initialize a single macro variable. That way you can break the long string into multiple tokens.
%let fname=B:\This\file\path\is\really\long\but\there\is\nothing;
%let fname=&fname\I\can\do\about\it\because\it\is\on\a\shared\network\drive\and\I\am\stuck;
%let fname=&fname\with\whatever\organization\or\lack\thereof\exists\for\directory\hierarchies;
%let fname=&fname\filename.txt;
Or you could use a DATA step to set your macro variable instead.
data _null_;
call symputx('fname',catx('\'
,'B:\This\file\path\is\really\long\but\there\is\nothing\I\can'
,'do\about\it\because\it\is\on\a\shared\network\drive\and\I\am\stuck'
,'with\whatever\organization\or\lack\thereof\exists\for\directory'
,'hierarchies\filename.txt'
));
run;
For a situation where you need to put a long string in code such as a dataset label or some type of description consider using %cmpres. The function has limits but is useful to keep one inside 80 columns if they can use it. Here, my CR and other adjacent white spaces are being "compressed" in to a single space character.
%macro get_filename(FILEPATH_FILE, FILE)
/DES=%cmpres("returns a file's name, placed into var FILE, removing the
file path from FILEPATH_FILE.");
If you do this a lot, use %SYSFUNC() and COMPRESS() to make a user-defined macro like this:
%macro c(text);
%sysfunc(compress(&text, ,s))
%mend;
filename infile %c("B:\This\file\path\is\really\long\but\there\is\nothing\I\
can\do\about\it\because\it\is\on\a\shared\network\drive\
and\I\am\stuck\with\whatever\organization\or\lack\thereof\
exists\for\directory\hierarchies\and\he\uses\B\as\a\drive\
OMG\who\does\that\filename.txt");
%put %c("B:\This\file\path\is\really\long\but\there\is\nothing\I\
can\do\about\it\because\it\is\on\a\shared\network\drive\
and\I\am\stuck\with\whatever\organization\or\lack\thereof\
exists\for\directory\hierarchies\and\he\uses\B\as\a\drive\
OMG\who\does\that\filename.txt");
Option "s" in the COMPRESS() function removes all whitespace characters.
SAS posts notes on the log, you can ignore them:
NOTE: The quoted string currently being processed has become more than 262 characters long. You might have unbalanced quotation marks.

Strip apostrophes from a character string (compress?)

I have a string which looks like this:
"ABAR_VAL", "ACQ_EXPTAX_Y", "ACQ_EXP_TAX", "ADJ_MATHRES2"
And I'd like it to look like this:
ABAR_VAL ACQ_EXPTAX_Y ACQ_EXP_TAX ADJ_MATHRES2
I.e. no apostrophes or commas and single space separated.
What is the cleanest / shortest way to do so in SAS 9.1.3?
Preferably something along the lines of:
call symput ('MyMacroVariable',compress(????,????,????))
Just to be clear, the result needs to be single space separated, devoid of punctuation, and contained in a macro variable.
Here you go..
data test;
var1='"ABAR_VAL", "ACQ_EXPTAX_Y", "ACQ_EXP_TAX", "ADJ_MATHRES2"';
run;
data test2;
set test;
call symput('macrovar',COMPBL( COMPRESS( var1,'",',) ) );
run;
%put &macrovar;
Is this part of an infile statement or are you indeed wanting to create macro variables that contain these values? If this is part of an infile statement you shouldn't need to do anything if you have the delimiter set properly.
infile foo DLM=',' ;
And yes, you can indeed use the compress function to remove specific characters from a character string, either in a data step or as part of a macro call.
COMPRESS(source<,characters-to-remove>)
Sample Data:
data temp;
input a $;
datalines;
"boo"
"123"
"abc"
;
run;
Resolve issue in a data step (rather than create a macro variable):
data temp2; set temp;
a=compress(a,'"');
run;
Resolve issue whilst generating a macro variable:
data _null_; set temp;
call symput('MyMacroVariable',compress(a,'"'));
run;
%put &MyMacroVariable.;
You'll have to loop through the observations in order to see the compressed values the variable for each record if you use the latter code. :)
To compress multiple blanks into one, use compbl : http://www.technion.ac.il/docs/sas/lgref/z0214211.htm