Hello-
I'm creating a set of macro variables that will sweep across a line of text and increment new values for "Start" and "End" fields based on the position of the pointer for the last value + 1. As the pointer sweeps across the line, it is searching for a specific character using the findc() function. Each time it finds that character, it uses that as the "End" value for the last field and the "Start" value for the next field plus 1:
Here's a sample of a line of text:
ƒƒƒƒƒƒƒƒƒˆƒƒƒƒƒƒƒƒˆƒƒƒƒƒƒƒƒˆƒƒƒƒƒƒƒƒˆƒƒƒƒƒƒƒƒˆƒƒƒƒƒƒƒƒˆƒƒƒƒƒƒƒƒˆƒƒƒƒƒƒƒƒˆ
So, we know that the text begins in column 9 and the specific character that the findc() function is seeking is the 'ˆ'. This means that for the first field, we can set the start value to 9 and the end value to 18 since the 'ˆ' is the 18th character in the text. For each successive field, based on the position of the 'ˆ', the start and end values look like this:
Field Start End
1 9 18
2 19 28
and so on
The thing that makes this challenging is that the the End position can fluctuate, based on the line of text being processed.
To assign the End values to a set of macro variables, I'm using the findc() function.
x=findc(text,'ˆ',start+1);
I can't use "call symput" to assign a macro variable with the value of x because that will only resolve once the data step is completed. Similarly, the %let End=x; or %let End=%eval(x); don't work.
How do I assign the value of "x" into a macro variable and use it in the same data step?
Thank you.
I'm very confused. Here is something like what @Astounding described. But personally, I've never had a situation where I had a DATA step in which I wanted to create macro variable from a data step variable and also use that macro variable within the same step. Which is to say, it's possible I've never used SYMGET in real life. So I'm guessing the below isn't really what you want. I think maybe you need to describe more of the big picture.
The below code parses a text string, makes an array of macro varaibles using CALL SYMPUTX that store the location of each delimiter, and also uses those macro variables in a trivial assignment statement via SYMGET:
265 data a; 266 text="0000*000*00*"; 267 start=findc(text,'*'); 268 do i=1 to countc(text,'*')-1; 269 end =findc(text,'*',start+1); 270 call symputx(cats("MacStart",i),start); 271 start=findc(text,'*',start+1); 272 end; 273 Start1=symget("MacStart1"); 274 Start2=symget("MacStart2"); 275 276 put (Text Start1 Start2)(=); 277 run; text=0000*000*00* Start1=5 Start2=9 NOTE: The data set WORK.A has 1 observations and 6 variables. 278 279 %put &MacStart1 &MacStart2; 5 9
That won't work because I want to carry the values forward within the macro.
The usual way (although legitimate applications are rare) to use a macro variable in the same DATA step is to retrieve it using SYMGET.
I suspect that this won't be sufficient here. It appears that you really need a set of macro variables, not just one. Consider naming macro variables START1, START2, etc. where the numeric suffix just increments each time you are moving on to the next segment of the text.
I would first look at the idea of creating DATA step variables. You can always output their (multiple) values to a separate data set, within the same DATA step. That would make them available later in the program.
Thank you.
In the interests of trying to keep my question simple, I didn't mention that there is an iterative string of macro variables that changes with the size of the text line.
And I am trying to do all of this within one data step.
So, the question remains, how do I assign a scalar value to a macro variable if "call symput" and "%let" assignments don't work?
You could create a single macro variable containing all the values:
You'll need to go through each number within the macro variable in later processing. It might look like the equivalent of:
%let starts = 11 18 27 35 42 98;
I'm very confused. Here is something like what @Astounding described. But personally, I've never had a situation where I had a DATA step in which I wanted to create macro variable from a data step variable and also use that macro variable within the same step. Which is to say, it's possible I've never used SYMGET in real life. So I'm guessing the below isn't really what you want. I think maybe you need to describe more of the big picture.
The below code parses a text string, makes an array of macro varaibles using CALL SYMPUTX that store the location of each delimiter, and also uses those macro variables in a trivial assignment statement via SYMGET:
265 data a; 266 text="0000*000*00*"; 267 start=findc(text,'*'); 268 do i=1 to countc(text,'*')-1; 269 end =findc(text,'*',start+1); 270 call symputx(cats("MacStart",i),start); 271 start=findc(text,'*',start+1); 272 end; 273 Start1=symget("MacStart1"); 274 Start2=symget("MacStart2"); 275 276 put (Text Start1 Start2)(=); 277 run; text=0000*000*00* Start1=5 Start2=9 NOTE: The data set WORK.A has 1 observations and 6 variables. 278 279 %put &MacStart1 &MacStart2; 5 9
Thanks to everyone for their helpful comments. Quentin, I've adapted your code into something like what I need for the challenge I'm facing. To your point, as of right now the symget function for "numx" isn't resolving.
options nomacrogen nomlogic nosymbolgen nomprint;
options macrogen mlogic symbolgen mprint;
%macro loops;
data a;
text=" ƒƒƒƒƒƒƒƒƒˆƒƒƒƒƒƒƒƒˆƒƒƒƒƒƒƒƒˆƒƒƒƒƒƒƒƒˆƒƒƒƒƒƒƒƒˆƒƒƒƒƒƒƒƒˆƒƒƒƒƒƒƒƒˆƒƒƒƒƒƒƒƒˆ";
start=findc(text,'ˆ');
do i=1 to countc(text,'ˆ');
end =findc(text,'ˆ',start+1);
call symputx(cats("MacStart",i),start);
start=findc(text,'ˆ',start+1);
end;
j=i-1;
call symputx('Num',put(j,3.));
Numx=symget("&&num");
put numx=;
/*
array startx Macstartx1 - Macstartx&&numx;
%do a=1 %to &&numx;
Startx=symget("MacStart&&a");
%end;
%put &num %do a=1 %to &&numx; &MacStart&&a %end;;
*/
run;
%put &num &numx;
%do a=1 %to &# &&&&MacStart&&a %end;;
%mend;
%loops
The part that's commented out presumes that &&numx resolves correctly.
Thanks again.
I'm struggling to keep this question manageable. Obviously, it's challenging enough as it is. I'm not opposed to describing what I'm trying to accomplish but am reluctant to do so. Doing so is no guarantee that the confusion will be resolved. It could well only add fuel to the fire.
That said, it sounds like correcting the ampersands for symget() won't work as hoped in the given data step. So, I'm back to the drawing board.
Thanks to everyone for their helpful suggestions.
Fortunately, no one has seen my code! That said, I'm sure it's not efficient but the suggestions that have been made have helped me get to a new, workable solution.
Thanks to all!
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.