Hi I think this is a very basic question.
why I can't use %scan or some other macro function inside of a datastep.
Is this because data step is reading value from PDV and %scan is creating a text?
%let a=%str(a_b);
data a;
a= "'"||%scan(&a,2,_)||"'";
run;
I wonder why the above program won't work.
please provide detailed explaination and refer me to any document if it is relevant.
Thanks
@gyambqt wrote:
But if I didn't use the || to concanate quotation mark together around b , I believe the treat b as a variable rather than value.
but here I used || so the final resolved value should be a='b'..... am I wrong?
a= "'"||%scan(&a,2,_)||"'";
Here you have three items that are concatenated:
- a string literal containing a single quote
- a macro call that will resolve to the text (not string literal!!) b and therefore be recognized as a variable name
- another string literal containing a single quote.
For the data step this means
"concatenate a single quote with the contents of b and another single quote"
To create the simple literal "b" for assignmenmt to data step variable a, use
a= "%scan(&a,2,_)";
The macro processor is a pre-processor. Anytime the SAS interpreter encounters a macro trigger (& or %), it sends all text of the trigger to the macro processor. This then deals with it and returns (or not, ie if a %put just writes to the log) text to the SAS interpreter for further execution.
So all macro triggers are resolved before a data or procedure step starts to run.
As a general rule use %scan when you are writing macro code statements and use the SCAN function in SAS code. Believe me it's a lot easier that way and it works:
%let a=%str(a_b);
data a;
a = scan("&a", 2, "_");
run;
It's partly what you mentioned (processing text vs. processing data in the PDV). But it's more than that. Macro language constructs your program. It doesn't process your data. Picture this stand-alone statement:
%let b = %scan(a,2,_);
Macro language would process the text "a", and would return a null string since there is no second word within the text "a".
In the context of your program, macro language does the same thing. It processes "a" before your DATA step begins to run, as part of the process of compiling the DATA step statements and determining what statements should become part of the DATA step. If you wanted macro language to return "b" instead (the second word within "a_b", you could get that with:
%let a = a_b;
%let b = %scan(&a,2,_);
But none of that processing takes place within a DATA step. All of it takes place as part of the compilation process that determines what statements the DATA step contains. So consider your original program:
%let a = a_b;
data a;
a= "'"||%scan(a,2,_)"'";
run;
%SCAN runs before the DATA step begins, and generates this program:
data a;
a= "'"||"'";
run;
The bottom line: macro language constructs a program. It doesn't process your data.
I wonder why %scan below can't resolved to "b"
%let a = a_b;
data a;
a= "'"||%scan(a,2,_)"'";
run;
i thought %scan would be resolved to b before data step get executed.
Sorry I had a typo error . The code is fixed now.
thanks
Even in your fixed code, a means a. It's just a letter. It has no connection to any variable in any DATA step. Macro language doesn't require quotes for it to treat characters as text. That's the default interpretation: characters are text whether they have quotes around them or not.
I don't quite understand.
Doesn't %scan(&a,2,_) resolved to %scan(a_b,2,_) further resolved to b?
b with quotation should be treated as value?
The ONE IMPORTANT question has not yet been asked: what are you trying to achieve? Do you want to parameterize the use of a data step variable in a data step, or do you want to parameterize a value in a data step?
In macro language, b is not a value. b is a letter that might be part of a SAS statement. For example, after generating b with the %SCAN function, you would have this statement:
%let a = a_b;
%let b = %scan(&a, 2, _);
The macro variable &b contains the letter b. But if it were part of this DATA step statement that would cause a problem:
%let a = a_b;
data a;
a= "'"||%scan(&a,2,_)"'";
run;
The DATA step statement would look like this:'
a = "'" ||b"'";
That's not a valid DATA step statement.
But if I didn't use the || to concanate quotation mark together around b , I believe the treat b as a variable rather than value.
but here I used || so the final resolved value should be a='b'..... am I wrong?
a= "'"||%scan(&a,2,_)||"'";
@gyambqt wrote:
But if I didn't use the || to concanate quotation mark together around b , I believe the treat b as a variable rather than value.
but here I used || so the final resolved value should be a='b'..... am I wrong?
a= "'"||%scan(&a,2,_)||"'";
Here you have three items that are concatenated:
- a string literal containing a single quote
- a macro call that will resolve to the text (not string literal!!) b and therefore be recognized as a variable name
- another string literal containing a single quote.
For the data step this means
"concatenate a single quote with the contents of b and another single quote"
To create the simple literal "b" for assignmenmt to data step variable a, use
a= "%scan(&a,2,_)";
Thanks!
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
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.