Hello.
I have been trying to make a macro function that counts the number of words in a given string. I use the function countw, but it seems it doesn't work correctly when applied to an empty string. My program is as follows.
%let words = ;
%macro no_of_words;
%if &words = " " %then %do;
amount = 0;
%end;
%else %do;
amount = %sysfunc(nwords(&words));
%end;
%mend;
data how_many;
%no_of_words´;
put amount;
run;
The error message from the log is "The function COUNTW referenced by the %SYSFUNC or %QSYSFUNC macro function has too few arguments."
The program works, if words contains a non-empty string. Any idea as to what my problem is, and how to avoid it?
Kind regards.
You have a couple of problems, beside the code you posted not being that which you ran. Does the following do what you want?
%let words = this is;
%macro no_of_words;
%if &words = /*" "*/ %then %do;
amount = 0;
%end;
%else %do;
amount = %sysfunc(countw(&words));
%end;
%mend;
data how_many;
%no_of_words
put amount;
run;
You have a couple of problems, beside the code you posted not being that which you ran. Does the following do what you want?
%let words = this is;
%macro no_of_words;
%if &words = /*" "*/ %then %do;
amount = 0;
%end;
%else %do;
amount = %sysfunc(countw(&words));
%end;
%mend;
data how_many;
%no_of_words
put amount;
run;
Hedegaard,
The fault lies in your first comparison:
%if &words = " " %then %do;
Macro language does not require quotes. This statement actually compares &WORDS to a set of 3 characters: a double quote, followed by a space, followed by another double quote.
This replacement would be acceptable:
%if &words = %then %do;
But this would be safer:
%if %length(&words)=0 %then %do;
There are some text strings that could appear within &WORDS that would cause trouble in the %IF comparison. This is one method to avoid that trouble.
This is the one I use:
%MACRO WORDS(STRING);
%sysfunc(countw(&string,' ,')) /*does this in 9.1 NOTE there is no ; if included it is returned as part of the value*/
%MEND;
Requires SAS 9.1 or later.
Returns 0 for an empty string. You could modify the delimiter list.
The "need" for this existed for me as I had a prior version dating back to SAS 6 from before the %sysfunc statement.
Thank you all.
art297: Yes, that is what I meant to write - sorry I got it mixed up.
Astounding: I now use
%if %length(&words)=0 %then %do
instead,
and it seems to work just fine.
Hedegaard,
See if this makes sense to you as a next step. Your macro would be much more widely applicable if it did NOT generate amount=, but merely generated the number. For example:
%macro no_of_words (words);
%if %length(&words)=0 %then 0;
%else %sysfunc(countw(&words, %str( )));
%mend no_of_words;
That last piece with a blank inside the parentheses -- %str( ) -- is the right way to use only blanks as delimiters. You would use the macro wherever you want the number to appear. For example:
data how_many;
amount = %no_of_words(&words);
put amount;
run;
It looks strange the first time you see it, but it's very practical and effective.
Don't miss out on SAS Innovate - Register now for the FREE Livestream!
Can't make it to Vegas? No problem! Watch our general sessions LIVE or on-demand starting April 17th. Hear from SAS execs, best-selling author Adam Grant, Hot Ones host Sean Evans, top tech journalist Kara Swisher, AI expert Cassie Kozyrkov, and the mind-blowing dance crew iLuminate! Plus, get access to over 20 breakout sessions.
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.