Lesson 10, Part 3a: %SYSFUNC and %QSYSFUNC Functions¶
%SYSFUNC function executes most of the data step functions.¶
“Because %SYSFUNC is a macro function, you do not need to enclose character values in quotation marks as you do in DATA step functions” (SAS® Documentation).
* Ex4_Percent_sysfunc.sas;
options nodate nonumber nonotes nosource;
ods html close;
**** Here is a DATA step ;
data _null_;
ds1 ='CLASS|CARS|HEART|DEMOGRAPHICS';
count_words_v1 = countw(ds1, '|');
put 'DATA step variable: ' DS1=;
put 'DATA step variable: ' count_words_v1= ;
run;
SAS Connection established. Subprocess id is 11592
4 The SAS System 13:05 Friday, November 13, 2020
28 ods listing close;ods html5 (id=saspy_internal) file=_tomods1 options(bitmap_mode='inline') device=svg style=HTMLBlue;
28 ! ods graphics on / outputfmt=png;
NOTE: Writing HTML5(SASPY_INTERNAL) Body file: _TOMODS1
29
30 * Ex4_Percent_sysfunc.sas;
31 options nodate nonumber nonotes nosource;
DATA step variable: ds1=CLASS|CARS|HEART|DEMOGRAPHICS
DATA step variable: count_words_v1=4
E3969440A681A2408885998500000004
**** Creating and displaying macro variables in open code;
options nodate nonumber nosource;
ods html close;
%let m_ds1 = CLASS|CARS|HEART|DEMOGRAPHICS;
%let m_count_words_v1 = %sysfunc(countw(&m_ds1, %str(|)) );
%put Macro variable: &=m_ds1;
%put Macro variable: &=m_count_words_v1;
%symdel m_ds1 m_count_words_v1/nowarn;
%put _user_;
The SAS System
Macro variable: M_DS1=CLASS|CARS|HEART|DEMOGRAPHICS
Macro variable: M_COUNT_WORDS_V1=4
E3969440A681A2408885998500000009
Things to notice in the SAS code in the following cell.¶
- The macro variable m_ds2 has a comma (,) in its value.
- The comma (,) is part of the macro variable value, not a delemter.
Question: How to mask the comma (,) - a special character (or token)?¶
Answer: Use the %quote macro quoting function to reference &m_ds2.¶
If you don't use %quote, SAS would treat the comma as a delimiter, which is meaningful in the countw function.
Read Patterson and Remigio, 2017 about macro quoting functions
options nodate nonumber nosource;
ods html close;
%let m_ds3 = "CLASS","CARS","HEART","DEMOGRAPHICS";
%let m_count_words_v3 = %sysfunc(countw(%quote(&m_ds3)));
%put Macro variable: &=m_ds3;
%put Macro variable: &=m_count_words_v3;
%put _user_;
%symdel m_ds3 m_count_words_v3/nowarn;
%put _user_;
The SAS System
Macro variable: M_DS3="CLASS","CARS","HEART","DEMOGRAPHICS"
Macro variable: M_COUNT_WORDS_V3=4
GLOBAL M_COUNT_WORDS_V3 4
GLOBAL M_DS3 "CLASS","CARS","HEART","DEMOGRAPHICS"
E3969440A681A2408885998500000010
options nonumber nocenter nodate nosource nosymbolgen;
ods html close;
%LET list = %str(sashelp.class sashelp.iris sashelp.retail);
/* Count # of values in the string */
%LET count=%sysfunc(countw(&list, %STR( )));
%put &=list;
%put &=count;
%macro doit;
%do i = 1 %to &count;
%put title&i %left(%unquote(%SCAN(&list, &i, %STR( ))));
%end;
%put _user_;
%mend doit;
%doit
Another example of %SYSFUNC¶
title;
options nodate nonumber nosource nonotes;
ods html close;
footnote1 "%sysfunc(date(),worddate.) Class Report";
proc print data=sashelp.class (obs=3);
run;
| Obs | Name | Sex | Age | Height | Weight |
|---|---|---|---|---|---|
| 1 | Alfred | M | 14 | 69.0 | 112.5 |
| 2 | Alice | F | 13 | 56.5 | 84.0 |
| 3 | Barbara | F | 13 | 65.3 | 98.0 |
options nodate nonumber nosource;
ods html close;
data _null_;
var1= 'STAT 4197';
var2 = translate(var1, '6', '4');
put 'DATA step variable:' var1= ;
put 'DATA step variable:' var2= ;
run;
%let m_var1 = STAT 4197;
%let m_var2 = %sysfunc(translate(&m_var1, 6, 4));
%put macro variable: &=m_var1;
%put macro variable: &=m_var2;
%symdel var1 var2 /nowarn;
The SAS System
DATA step variable:var1=STAT 4197
DATA step variable:var2=STAT 6197
macro variable: M_VAR1=STAT 4197
macro variable: M_VAR2=STAT 6197
E3969440A681A2408885998500000008
%SYSFUNC and PUTN only take macro variables, not data step variables.¶
options nodate nonumber nosource;
ods html close;
%let x1=%sysfunc(today(),date9.);
%let x2=%sysfunc(today(),monname3.);
%let x3=%sysfunc(today(),day2.);
%let x4=%sysfunc(today(),year4.);
%let x5 =%sysfunc(putn('27jan2016'd, date9.));
%let x6 =%sysfunc(putn(0, date9.));
%let x7 =%sysfunc(inputn(04jul2016, date9.));
%let x7 =%sysfunc(putn(%sysfunc(inputn(04jul2016, date9.)), mmddyy10.));
%let x9=%sysfunc(datetime(), datetime.);
%let x10=%sysfunc(date(),worddate.);
%let x11= %sysfunc(left(%qsysfunc(date(),worddate32.)));
%put &=x1 &=x2 &=x3 &=x4 &=x5 &=x6 ;
%put &=x7 &=x8 &=x9;
%put &=x10 &=x11;
%symdel x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11/nowarn;
The SAS System
X1=27OCT2019 X2=Oct X3=27 X4=2019 X5=27JAN2016 X6=01JAN1960
X7=07/04/2016 X8=27OCT19:15:43:33 X9=27OCT19:15:57:29
X10=October 27, 2019 X11=October 27, 2019
E3969440A681A2408885998500000088
Below the LEFT function expects only one argument, but you are passing "November 24, 2020" to it. It interprets the comma as the delimiter between two arguments.
You can mask the comma by using the %QSYSFUNC function instead, as follows:
options nodate nonumber nosource;
ods html close;
title "%sysfunc(left(%qsysfunc(today(),worddate32.))) Student Report";
proc print data=sashelp.class (obs=5); run;
| Obs | Name | Sex | Age | Height | Weight |
|---|---|---|---|---|---|
| 1 | Alfred | M | 14 | 69.0 | 112.5 |
| 2 | Alice | F | 13 | 56.5 | 84.0 |
| 3 | Barbara | F | 13 | 65.3 | 98.0 |
| 4 | Carol | F | 14 | 62.8 | 102.5 |
| 5 | Henry | M | 14 | 63.5 | 102.5 |
options nonotes nodate nonumber nosource;
ods html close;
%put %sysfunc(intnx(month,%sysfunc(today()),1),monname8.);
%put %sysfunc(intnx(month,%sysfunc(today()),-1,s),year.);
%put %sysfunc(intnx(year,%sysfunc(today()),2),year.);
The SAS System
November
2019
2021
E3969440A681A2408885998500000023
*SAS Documentation 9.4;
%macro checkds(dsn);
%if %sysfunc(exist(&dsn)) %then
%do;
proc print data=&dsn;
run;
%end;
%else
%put The data set &dsn does not exist.;
%mend checkds;
%checkds(Sasuser.Houses)
Challenge¶
How to replace commas in a macro variable and put spaces
"You will need to macro quote both commas and spaces to get them to be treated as text instead of delimiters." (Solution by Tom SUPER USER)
The %SYSFUNC enables the macro facility to execute SAS language functions or user-written funtions in open code (SAS Documentation).
options nocenter nonumber nodate nonotes nosource;
ods html close;
%let have = a,b,c;
%let want = %sysfunc(translate(%quote(&have),%str( ),%str(,)));
%put &=want;
The SAS System
WANT=a b c
E3969440A681A2408885998500000027
options nocenter nonumber nodate nonotes nosource;
ods html close;
data _null_;
have = 'a,b,c';
want = translate(have, ' ', ',');
put (_ALL_) (=);
The SAS System
have=a,b,c want=a b c
E3969440A681A2408885998500000035
%QSYSFUNC function additionally masks special characters and mnemonic operators.¶
%SYSFUNC does not mask special characters or mnemonic operators in its result. %QSYSFUNC masks the following special characters and mnemonic operators in its result:
& % ' " ( ) + − * / < > = ¬ ^ ~ ; , # blank
AND OR NOT EQ NE LE LT GE GT IN
options nocenter nonumber nodate nonotes nosource;
ods html close;
%let asthma_vars17 = ASTHDX ASSTIL31 ASATAK31 PERWT17F VARSTR VARPSU;
%let q_asthma_vars17 = %unquote(%str(%')%qsysfunc(tranwrd(%sysfunc(compbl(&asthma_vars17)),%str( ),' '))%str(%'));
%put &=asthma_vars17;
%put &=q_asthma_vars17;
The SAS System ASTHMA_VARS17=ASTHDX ASSTIL31 ASATAK31 PERWT17F VARSTR VARPSU Q_ASTHMA_VARS17='ASTHDX' 'ASSTIL31' 'ASATAK31' 'PERWT17F' 'VARSTR' 'VARPSU' The SAS System E3969440A681A2408885998500000010
ods html close;
options nocenter nonumber nodate nonotes nosource;
%let asthma_vars17 = ASTHDX ASSTIL31 ASATAK31 PERWT17F VARSTR VARPSU;
%let s_asthma_vars17 = %str(%')%qsysfunc(tranwrd(%sysfunc(compbl(&asthma_vars17)),%str( ),' '))%str(%');
%put _user_;
The SAS System GLOBAL ASTHMA_VARS17 ASTHDX ASSTIL31 ASATAK31 PERWT17F VARSTR VARPSU GLOBAL S_ASTHMA_VARS17 ASTHDX ASSTIL31 ASATAK31 PERWT17F VARSTR VARPS The SAS System E3969440A681A2408885998500000008
%QSYSFUNC function additionally masks special characters and mnemonic operators. %SYSFUNC does not mask special characters or mnemonic operators in its result. %QSYSFUNC masks the following special characters and mnemonic operators in its result: & % ' " ( ) + − * / < > = ¬ ^ ~ ; , # blank AND OR NOT EQ NE LE LT GE GT IN
options nocenter nonumber nodate nonotes nosource;
ods html close;
%let asthma_vars17 = ASTHDX ASSTIL31 ASATAK31 PERWT17F VARSTR VARPSU;
%let q_asthma_vars17 = %unquote(%str(%')%qsysfunc(tranwrd(%sysfunc(compbl(&asthma_vars17)),%str( ),' '))%str(%'));
%put &=asthma_vars17;
%put &=q_asthma_vars17;
The SAS System ASTHMA_VARS17=ASTHDX ASSTIL31 ASATAK31 PERWT17F VARSTR VARPSU Q_ASTHMA_VARS17='ASTHDX' 'ASSTIL31' 'ASATAK31' 'PERWT17F' 'VARSTR' 'VARPSU' The SAS System E3969440A681A2408885998500000012
When a macro variable is created with a macro quoting function like %STR or %QSYSFUNC, the function uses unprintable delta characters to mask the special characters in the macro variable's value.
These delta characters can cause unexpected syntax errors when the macro variable is used in non-macro syntax. Above, the macro variable has resolved, and the syntax error occurred during tokenization.
Solution: Use the %UNQUOTE function to remove the delta characters and prevent possible syntax errors caused by the characters.