Download presentation
Presentation is loading. Please wait.
1
How Best to Use Macro Quoting Functions?
Arthur Li City of Hope National Medical Center
2
Intro The macro language is a character-based language.
The purpose of using the macro language is used to generate SAS codes. Conflicts: %macro_call, ¯o_var; sometimes, & and % signs need to be treated simply as texts The mnemonics, OR or GE, are operators; In some situation, they only need to be interpreted as texts Use the macro quoting functions to mask the special meanings so that the macro processor will be able to interpret them correctly.
3
Intro %let print_foo = proc print data=foo; run;; %put &print_foo; SAS log: 216 %let print_foo = proc print data=foo; run;; 217 %put &print_foo; proc print data=foo The first semicolon ends the %LET statement; which should be interpreted as plain text.
4
Intro %let initial = %substr(&name, 1, 1);
%let name = Doe, John; %let initial = %substr(&name, 1, 1); %put &initial; SAS log: 228 %let name = Doe, John; 229 %let initial = %substr(&name, 1, 1); ERROR: Macro function %SUBSTR has too many arguments. 230 %put &initial; %let initial = %substr(&name, 1, 1); %let initial = %substr(Doe, John, 1, 1);
5
Macro Quoting Functions Types
The macro processor use the macro quoting functions to mask the following characters and mnemonics: & % blank , ; + - * / < > = ┑^ ~ # | ' " ( ) AND OR NOT EQ NE LE LT GE GT IN Compilation and execution quoting functions.
6
Macro Quoting Functions Types
Commonly-used macro quoting functions: %STR, %NRSTR %BQUOTE, %NRBQUOTE %SUPERQ Compilation quoting functions: During the macro compilation phase, using %STR and %NRSTR to treat characters as text in the macro program. Other macro quoting functions are mostly used during the macro execution. During the macro execution, the execution macro functions mask resolved values from macro variables.
7
Macro Quoting Functions Types
The function that begins with NR (non-resolved), such as %NRSTR, masks all the special characters, prevents macro or macro variable resolution. The function that does not begin with NR, such as %STR, masks the special characters except for ampersands (&) and percent signs (%). The functions that with letter B (for “by itself”), such as %BQUOTE and %NRBQUOTE are useful for quoting unmatched quotation marks or parentheses. & % blank , ; + - * / < > = ┑^ ~ # | ' " ( ) AND OR NOT EQ NE LE LT GE GT IN
8
Compilation Quoting Functions
The %STR and %NRSTR functions mask special characters and mnemonics during the macro compilation phase. %STR(character-string) %NRSTR(character-string) The %STR function does not mask & and %. When masking ' " ( ), we need to place a percent sign (%) in front of these characters.
9
Compilation Quoting Functions
Situations: When a user types special characters in the open code, such as in the %LET or %PUT statements. They can also be used in a programming logic statement such as %IF statement. When a user supplies parameter values on a macro call.
10
The %STR Function %let print_foo = proc print data=foo; run;;
%put &print_foo;
11
The %STR Function Correction:
%let print_foo = proc print data=foo; run;; %put &print_foo; Correction: %let print_foo = %str(proc print data=foo; run;); %put &print_foo;
12
The %STR Function Correction:
%let print_foo = proc print data=foo; run;; %put &print_foo; Correction: %let print_foo = %str(proc print data=foo; run;); %put &print_foo; %let print_foo = proc print data=foo%str(;) run%str(;); %put &print_foo; SAS log: 4 %let print_foo = %str(proc print data=foo; run;); 5 %put &print_foo; proc print data=foo; run;
13
The %STR Function SAS log: %macro first_last(name);
%let first = %scan(&name, 2); %let last = %scan(&name, 1); %put &first &last; %mend; %first_last(Doe, John) SAS log: 263 %first_last(Doe, John) ERROR: More positional parameters found than defined.
14
The %STR Function SAS log: Correction: %macro first_last(name);
%let first = %scan(&name, 2); %let last = %scan(&name, 1); %put &first &last; %mend; %first_last(Doe, John) SAS log: 263 %first_last(Doe, John) ERROR: More positional parameters found than defined. Correction: %first_last(%str(Doe, John))
15
The %STR Function Use comma(,) as the delimiter: SAS log:
%macro first_last1(name); %let first = %scan(&name, 2, ,); %let last = %scan(&name, 1, ,); %put &first &last; %mend; %first_last1(%str(Doe, John)) SAS log: 15 %first_last1(%str(Doe, John)) Doe, John Having two consecutive commas causes %SCAN to use the NULL value as the delimiter
16
The %STR Function Correction: SAS log: %macro first_last1(name);
%let first = %scan(&name, 2, %str(,)); %let last = %scan(&name, 1, %str(,)); %put &first &last; %mend; %first_last1(%str(Doe, John)) SAS log: 36 %first_last1(%str(Doe, John)) John Doe
17
The %STR Function Preserve the leading blanks in the %PUT statement
%macro first_last2(name); %let first = %scan(&name, 2, %str(, )); %let last = %scan(&name, 1, %str(, )); %put %str( &first &last); %mend; %first_last2(%str(Doe, John)) SAS log: 42 %first_last2(%str(Doe, John)) John Doe
18
The %STR Function SAS log: %macro compare_brand(brand);
%if &brand = GE %then %put Brand is General Electric; %else %put Brand is &brand; %mend; %compare_brand(Coke) SAS log: 50 %compare_brand(Coke) Brand is General Electric
19
The %STR Function Syntactically correct expression: &brand = GE
%macro compare_brand(brand); %if &brand = GE %then %put Brand is General Electric; %else %put Brand is &brand; %mend; %compare_brand(Coke) Syntactically correct expression: &brand = GE ((&brand =) GE)
20
The %STR Function SAS log: %macro compare_brand1(brand);
%if &brand = %str(GE) %then %put Brand is General Electric; %else %put Brand is &brand; %mend; %compare_brand1(Coke) SAS log: 56 %compare_brand1(Coke) Brand is Coke
21
The %NRSTR Function The %NRSTR function masks all the characters that the %STR function masks. %NRSTR also masks & and %. %let ice_cream = %str(Ben&Jerry); %put &ice_cream; SAS log: 57 %let ice_cream = %str(Ben&Jerry); WARNING: Apparent symbolic reference JERRY not resolved. 58 %put &ice_cream; Ben&Jerry
22
The %NRSTR Function The %NRSTR function masks all the characters that the %STR function masks. %NRSTR also masks & and %. %let ice_cream = %nrstr(Ben&Jerry); %put &ice_cream; SAS log: 59 %let ice_cream = %nrstr(Ben&Jerry); 60 %put &ice_cream; Ben&Jerry
23
Situation for using %STR, but not %NRSTR
%let printlast = %nrstr(proc print data=&syslast; run;); &printlast SAS log: 731 %let printlast = %nrstr(proc print data=&syslast; run;); 732 &printlast NOTE: Line generated by the macro variable "PRINTLAST". roc print data=&syslast; run; - 22 200 ERROR: File WORK.SYSLAST.DATA does not exist. ERROR : Expecting a name. ERROR : The symbol is not recognized and will be ignored.
24
Situation for using %STR, but not %NRSTR
%let printlast = %nrstr(proc print data=&syslast; run;); &printlast Correction: %let printlast = %str(proc print data=&syslast; run;); &printlast
25
Execution Quoting Functions
The situations for using macro execution quoting functions: Mask the resolved value of a macro variable during macro invocation Mask the result from a macro function or in macro programming logic It is useful to mask the characters that were entered by users but unknown to us and these characters might cause programming errors.
26
The %BQUOTE and %NRBQUOTE Functions
%BQUOTE and %NRBQUOTE: mask special characters and mnemonic operators in a resolved value at macro execution. %BQUOTE(character-string | text-expression) %NRBQUOTE(character-string | text-expression) the %BQUOTE function does not masks ampersand (&) and percent (%) signs
27
The %BQUOTE and %NRBQUOTE Functions
%macro compare_brand1(brand); %if &brand = %str(GE) %then %put Brand is General Electric; %else %put Brand is &brand; %mend; %compare_brand1(GE) SAS log: 315 %compare_brand1(GE) Brand is GE
28
The %BQUOTE and %NRBQUOTE Functions
%macro compare_brand1(brand); %if &brand = %str(GE) %then %put Brand is General Electric; %else %put Brand is &brand; %mend; %compare_brand1(%str(GE)) SAS log: 317 %compare_brand1(%str(GE)) Brand is General Electric
29
The %BQUOTE and %NRBQUOTE Functions
What if we can’t control what the user is going to use when calling the macro? %macro compare_brand2(brand); %if %bquote(&brand) = %str(GE) %then %put Brand is General Electric; %else %put Brand is &brand; %mend; %compare_brand2(GE) SAS log: 333 %compare_brand2(GE) Brand is General Electric
30
The %BQUOTE and %NRBQUOTE Functions
Both methods work: when you mask a special character with a macro quoting function, it remains masked as long as it is within the macro facility %macro compare_brand1(brand); %if &brand = %str(GE) %then %put Brand is General Electric; %else %put Brand is &brand; %mend; %compare_brand1(%str(GE)) %macro compare_brand2(brand); %if %bquote(&brand) = %str(GE) %then %put Brand is General Electric; %else %put Brand is &brand; %mend; %compare_brand2(GE)
31
The %BQUOTE and %NRBQUOTE Functions
%macro addplus1(number); %let first = %substr(&number, 1, 1); %if &first EQ 1 %then %do; %let newnumber = +&number;; %end; %else %if &first NE %str(+) %then %do; %let newnumber = +1&number;; %else %let newnumber = &number; %put &newnumber; %mend; %addplus1((909) ) %addplus1(1(909) ) %addplus1(%str(+)1(909) )
32
The %BQUOTE and %NRBQUOTE Functions
SAS log: 365 %addplus1((909) ) +1(909) 366 %addplus1(1(909) ) 367 %addplus1(%str(+)1(909) ) ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric operand is required. The condition was: &first EQ 1 ERROR: The macro ADDPLUS1 will stop executing.
33
The %BQUOTE and %NRBQUOTE Functions
%macro addplus1(number); %let first = %substr(&number, 1, 1); %if &first EQ 1 %then %do; %let newnumber = +&number;; %end; %else %if &first NE %str(+) %then %do; %let newnumber = +1&number;; %else %let newnumber = &number; %put &newnumber; %mend; %addplus1(%str(+)1(909) ) The masking applies to “+” sign that is removed when the macro variable is resolved in the %SUBSTR function.
34
The %BQUOTE and %NRBQUOTE Functions
%macro addplus1(number); %let first = %substr(&number, 1, 1); %if &first EQ 1 %then %do; %let newnumber = +&number;; %end; %else %if &first NE %str(+) %then %do; %let newnumber = +1&number;; %else %let newnumber = &number; %put &newnumber; %mend; %addplus1(%str(+)1(909) ) Incorrect expression: &first EQ 1 + EQ 1
35
The %BQUOTE and %NRBQUOTE Functions
%macro addplus2(number); %let first = %substr(&number, 1, 1); %if %bquote(&first) EQ 1 %then %do; %let newnumber = +&number;; %end; %else %if %bquote(&first) NE %str(+) %then %do; %let newnumber = +1&number;; %else %let newnumber = &number; %put &newnumber; %mend; %addplus2((909) ) %addplus2(1(909) ) %addplus2(+1(909) )
36
The %BQUOTE and %NRBQUOTE Functions
SAS log: 380 %addplus2((909) ) +1(909) 381 %addplus2(1(909) ) 382 %addplus2(+1(909) )
37
The %BQUOTE and %NRBQUOTE Functions
%NRBQUOTE is similar to %BQUOTE except that the %NRBQUOTE function masks & and % signs in the resolved value of an argument. %macro add_ampersand(number); %let first = %substr(&number, 1, 1); %if %nrbquote(&first) EQ %nrstr(&) %then %do; %let newnumber = &number;; %end; %else %let newnumber =%nrstr(&)&number; %put &newnumber; %mend; %add_ampersand(&123) %add_ampersand(123) 402 %add_ampersand(&123) &123 403 %add_ampersand(123)
38
The %QUOTE and %NRQUOTE Functions
The %QUOTE and %NRQUOTE functions are similar to %BQUOTE and %NRBQUOTE functions. Both of these functions are used during the macro execution phase The %BQUOTE and %NRBQUOTE functions do not require that quotation marks without a match be marked with a preceding % sign, and %QUOTE and %NRQUOTE do. With the availability of the %BQUOTE and %NRBQUOTE functions, the %QUOTE and %NRQUOTE functions are rarely used.
39
The %SUPERQ Function The %SUPERQ function also masks special characters and mnemonics during macro execution, and it prevents further resolution of the value. %SUPERQ(argument) argument: the name of a macro variable with no leading ampersand. a text expression that produces the name of a macro variable without a leading ampersand. Unlike other macro quoting functions, we can only use the %SUPERQ function to apply on one single macro variable.
40
The %SUPERQ Function %let name = Doe, John;
%let initial = %substr(%superq(name), 1, 1); %put &initial; 404 %let name = Doe, John; 405 %let initial = %substr(%superq(name), 1, 1); 406 %put &initial; D
41
The %SUPERQ Function The methods above yield the same result.
%let name = Doe, John; %let initial = %substr(%superq(name), 1, 1); %put &initial; %let name = %str(Doe, John); %let initial = %substr(&name, 1, 1); %put &initial; %let name = Doe, John; %let initial = %substr(%bquote(&name), 1, 1); %put &initial; The methods above yield the same result.
42
The %SUPERQ Function Both %NRBQUOTE and %SUPERQ functions mask % and & signs. When using the %NRBQUOTE function, the macro processor masks the argument after the macro processor resolves macro variable references or values. On the other hand, the macro processor masks the argument of the %SUPERQ function before it resolves any macro variable references or values.
43
The %SUPERQ Function When using the %NRBQUOTE function, the macro processor masks the argument after the macro processor resolves macro variable references or values. data _null_; call symput('ice_cream', 'Ben&Jerry'); run; %let phrase = See you at %nrbquote(&ice_cream); %put &phrase; SAS log: 525 %let phrase = See you at %nrbquote(&ice_cream); WARNING: Apparent symbolic reference JERRY not resolved. 526 %put &phrase; See you at Ben&Jerry
44
The %SUPERQ Function On the other hand, the macro processor masks the argument of the %SUPERQ function before it resolves any macro variable references or values. data _null_; call symput('ice_cream', 'Ben&Jerry'); run; %let phrase = See you at %superq(ice_cream); %put &phrase; SAS log: 528 %let phrase = See you at %superq(ice_cream); 529 %put &phrase; See you at Ben&Jerry
45
Quoting Function Results
%macro addplus1(number); %let first = %substr(&number, 1, 1); %if &first EQ 1 %then %do; %let newnumber = +&number;; %end; %else %if &first NE %str(+) %then %do; %let newnumber = +1&number;; %else %let newnumber = &number; %put &newnumber; %mend; %addplus1(%str(+)1(909) ) The masking applies to “+” sign that is removed when the macro variable is resolved in the %SUBSTR function.
46
Quoting Function Results
%macro addplus3(number); %let first = %qsubstr(&number, 1, 1); %if &first EQ 1 %then %do; %let newnumber = +&number;; %end; %else %if &first NE %str(+) %then %do; %let newnumber = +1&number;; %else %let newnumber = &number; %put &newnumber; %mend; %addplus3(%str(+)1(909) ) Alternative method: use %QSUBSTR function to mask the result.
47
Quoting Function Results
%macro first_last(name); %let first = %scan(&name, 2); %let last = %scan(&name, 1); %put &first &last; %mend; %first_last(%str(O%'Hara, Scarlett)) SAS log: %first_last(%str(O%'Hara, Scarlett)) ERROR: Literal contains unmatched quote. ERROR: The macro FIRST_LAST will stop executing.
48
Quoting Function Results
%macro first_last(name); %let first = %scan(&name, 2); %let last = %scan(&name, 1); %put &first &last; %mend; %first_last(%str(O%'Hara, Scarlett)) During the macro execution: &NAME “O’Hara, Scarlett” in the local symbol table. LOCAL SYMBOL TABLE User-Defined Macro Variables Name O'Hara, Scarlett
49
Quoting Function Results
%macro first_last(name); %let first = %scan(&name, 2); %let last = %scan(&name, 1); %put &first &last; %mend; %first_last(%str(O%'Hara, Scarlett)) During the macro execution: &First “Scarlett” in the local symbol table. LOCAL SYMBOL TABLE User-Defined Macro Variables Name O'Hara, Scarlett First Scarlett
50
Quoting Function Results
%macro first_last(name); %let first = %scan(&name, 2); %let last = %scan(&name, 1); %put &first &last; %mend; %first_last(%str(O%'Hara, Scarlett)) During the macro execution: The macro reference is resolved first The result from the %SCAN function becomes “O’Hara”. The masking applies to the apostrophe that is then removed LOCAL SYMBOL TABLE User-Defined Macro Variables Name O'Hara, Scarlett First Scarlett
51
Quoting Function Results
%macro first_last(name); %let first = %scan(&name, 2); %let last = %scan(&name, 1); %put &first &last; %mend; %first_last(%str(O%'Hara, Scarlett)) During the macro execution: %let last = O'Hara; The semicolon that ends the %LET statement becomes part of the literal. Since there is no ending single quote, the error message is generated. LOCAL SYMBOL TABLE User-Defined Macro Variables Name O'Hara, Scarlett First Scarlett
52
Quoting Function Results
Correction: %macro first_last3(name); %let first = %qscan(&name, 2); %let last = %qscan(&name, 1); %put &first &last; %mend; %first_last3(%str(O%'Hara, Scarlett)) %macro first_last4(name); %let first = %bquote(%scan(&name, 2)); %let last = %bquote(%scan(&name, 1)); %put &first &last; %mend; %first_last4(%str(O%'Hara, Scarlett))
53
Quoting Function Results
*Q equivalent Functions: %QSCAN %QCMPRES %QLEFT %QLOWCASE %QSUBSTR %QTRIM %QUPCASE %QSYSFUNC.
54
Invisible Characters 574 %put _user_; GLOBAL ICE Ben&Jerry
GLOBAL ICE_CREAM Ben&Jerry GLOBAL INITIAL D GLOBAL NAME Doe, John GLOBAL PHRASE See you at _Ben_Jerry_ GLOBAL PRINT_FOO _proc print data_foo_ run__ GLOBAL PRINT_FOO1 proc print data=foo___ run___ GLOBAL WORD BEN&JERRY
55
Unquoting When special characters or mnemonics are masked, they will be unmasked in the following conditions: They are resolved in the macro functions, such as the %SCAN, %SUBSTR, etc. Generally, they are remained masked as long as they are remained in the macro facility.
56
Unquoting If the texts are masked, the generated SAS statements appear to be correct, but the compiler often does not recognize them as valid syntax. To explicitly unmask text, use %UNQUOTE %UNQUOTE(character-string | text-expression)
57
Unquoting data example; input a b c; datalines; 100 200 300 ;
%macro scale(varname); %local i new; data; set example; %do i = 1 %to %sysfunc(countw(&varname)); %let new = %qscan(&varname, &i); val&new = &new/100; %end; run; %mend; %scale(a b)
58
Unquoting 2108 %scale(a b) NOTE: Line generated by the macro variable "NEW". vala --- 180 valb ERROR : Statement is not valid or it is used out of proper order. NOTE: The SAS System stopped processing this step because of errors.
59
Unquoting %macro scale(varname); %local i new; data; set example;
%do i = 1 %to %sysfunc(countw(&varname)); %let new = %qscan(&varname, &i); %unquote(val&new) = &new/100; %end; run; %mend;
60
Conclusion A general rule to choose the correct macro quoting function: If we can see the special character or mnemonics, we need to use the compilation quoting functions. If we cannot see the special character or mnemonics, we need to use the execution quoting functions.
61
References Burlew, Michele M. 2014, SAS® Macro Programming Made Easy, 3nd Edition, Cary, NC: SAS Institute Inc. Carpenter, Art L., 2006, Carpenter’s Complete Guide to the SAS® Macro Language, 3nd Edition, Cary, NC: SAS Institute Inc. Rosenbloom Mary F. O. and Carpenter, Art L., 2013, “Macro Quoting to the Rescue: Passing Special Characters”, Proceedings of SAS Global Forum 2013. SAS® Macro Language 2: Developing Macro Application Course Notes, 2009, Cary, NC: SAS Institute Inc. Tyndall, Russ, 2014, “Macro Quoting Made Easy”, Whitlock, Ian, “A Serious Look Macro Quoting”, Proceedings of SUGI28.
62
Acknowledgement I would like to thank Art Carpenter for his valuable programming suggestions and insight.
63
Contact Information Arthur Li City of Hope National Medical Center Department of Information Science 1500 East Duarte Road Duarte, CA Work Phone: (626) ext
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.