I have a counter in my code that is as follows: %let counter = %sysfunc(countw(&&CLMNS&j.)); However this does not work properly for some macro variables. For variable_1, which contains the values Parent_Name, Name the counter returns as 3 (should be 2). For variable_2, which contains Alt_Parent_Name, Alt_Name the counter correctly returns a value of 2.
If I add a pair of parentheses, so it now is: %let counter = %sysfunc(countw((&&CLMNS&j.)));, it now correctly outputs a value of 2 for both variable_1 and variable_2.
I have read through the help cards to no avail and would like to figure out why this occurs and what the extra parentheses do. I am mostly confused by the inconsistency of the result in the first instance.
Perhaps this helps:
SAS will break it down in the following order:
%let counter = %sysfunc(countw(&&CLMNS&j.));
&&) resolves to one ampersand (&) and the scanner continues.&j. in the global symbol table. E.g. to 1.&CLMNS1 in the global symbol table. E.g. to variable_1 (which would have to be resolved with another ampersand) or just Parent_Name, Name.%let counter = %sysfunc(countw(Parent_Name, Name));Now you can perhaps see what is going wrong. When the compiler continues, it will understand Name as the optional argument <character(s)> in countw.
What you want is instead to mask the output of &&CLMNS&j. for the macro processor. I.e. use %NRSTR:
%let counter = %sysfunc(countw(%NRSTR(&&CLMNS&j.)));
Expected global symbol table:
%PUT _ALL_;
GLOBAL J 1
GLOBAL CLMNS1 parent_name, name
GLOBAL CLMNS2 alt_parent_name, alt_name
AUTOMATIC ....
These resources might be relevant for you:
The extra parentheses prevent the comma in the value of the macro variable from being seen as delimiting the arguments to the function call.
If you pass COUNTW() two arguments the second is the list of characters that are used as delimiters. So 3 is the right answer when counting the words in Parent_name using the letters Name as the delimiters. Replacing the delimiters with periods you get: P.r.nt_n...
108 %put %sysfunc(countw(Parent_name,Name));
3
109 %put %scan(Parent_name,1,Name);
P
110 %put %scan(Parent_name,2,Name);
r
111 %put %scan(Parent_name,3,Name);
nt_n
112 %put %scan(Parent_name,4,Name);
But if you add the parentheses the comma is part of the string (the parentheses are also part of the string but since they are in the list of default delimiters they are ignored).
126 %put %sysfunc(countw((Parent_name,Name)));
2
127 %put %scan((Parent_name,Name),1);
Parent_name
128 %put %scan((Parent_name,Name),2);
Name
129 %put %scan((Parent_name,Name),3);
You can add macro quoting to prevent the comma from being seen as delimiting the arguments.
151 %let clmns=variable;
152 %let j=1;
153 %let &clmns&j=Parent_name,Name ;
154
155 %put %sysfunc(countw(%superq(&CLMNS&j)));
2
156 %put %scan(%superq(&CLMNS&j),1);
Parent_name
157 %put %scan(%superq(&CLMNS&j),2);
Name
But the easiest solution is to NOT use comma as the delimiter in your string and explicitly tell COUNTW() and SCAN() what delimiter you are using.
130 %let clmns=variable;
131 %let j=1;
132 %let &clmns&j=Parent_name|Name ;
133
134 %put %sysfunc(countw(&&&CLMNS&j,|));
2
135 %put %scan(&&&clmns&j,1,|);
Parent_name
136 %put %scan(&&&clmns&j,2,|);
Name
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With