Resolving variable value as a macro variable value

Accepted Solution Solved
Reply
Contributor
Posts: 59
Accepted Solution

Resolving variable value as a macro variable value

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.

 


Accepted Solutions
Solution
‎03-06-2016 07:30 AM
PROC Star
Posts: 1,227

Re: Resolving variable value as a macro variable value

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

View solution in original post


All Replies
Super User
Posts: 5,254

Re: Resolving variable value as a macro variable value

I have no clue of what you ate trying to do. But for you final question - it's sounds like an unnecessary round robin to create a macro variable that you wish to use in the same data step. Why not use a data step variable?
Data never sleeps
Contributor
Posts: 59

Re: Resolving variable value as a macro variable value

That won't work because I want to carry the values forward within the macro.

Super User
Posts: 5,071

Re: Resolving variable value as a macro variable value

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.

Contributor
Posts: 59

Re: Resolving variable value as a macro variable value

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?

Super User
Posts: 5,071

Re: Resolving variable value as a macro variable value

You could create a single macro variable containing all the values:

 

  • Create a long character variable in the DATA step
  • Append to that character variable every time you find a new START value, leaving a single blank before appending
  • At the end of the DATA step, CALL SYMPUT takes a long string and copies it to a macro variable

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;

 

 

Solution
‎03-06-2016 07:30 AM
PROC Star
Posts: 1,227

Re: Resolving variable value as a macro variable value

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
Super User
Posts: 5,254

Re: Resolving variable value as a macro variable value

Ok. If understand correctly you are defining the boundaries for "words" in a line of "text".
You have several lines of text, right?
For me being able to help further I think knowing about the requirement would help. What are you going to do with the macro variables? What will be the end product of this processing (show a sample for this as well).
Data never sleeps
Contributor
Posts: 59

Re: Resolving variable value as a macro variable value

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.

PROC Star
Posts: 1,227

Re: Resolving variable value as a macro variable value

I think @LinusH is right. People could help better if you described the full problem and desired result. It's not clear if the macro language will be helpful.

That said, when you code:
call symputx('Num',put(j,3.));
Numx=symget("&&num");
The first line makes a macro variable named Num. If you want to use SYMGET to read the value of that macro var, it would be Numx=symget("Num"). No ampersands. As written it will try to resolve macro reference &&Num when the step compiles. Which won't work.

That said, in the commented out code you are trying to use &&Numx on an array statement. There is no NUMX macro var created anywhere. Even if it were created during the execution of this data step, it could not be used to define an array in the same step, because the array statement works at compile time.

I think if you describe the desired output you want from your input text string (or perhaps 2 or 3 text strings), people will be able to help better.

(Apologies for formatting, I'm on my phone)
Contributor
Posts: 59

Re: Resolving variable value as a macro variable value

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.

Super User
Posts: 17,750

Re: Resolving variable value as a macro variable value

If the collective experience above look at your code and say its too convoluted, it likely is. It's mostly a matter of do you want to get your way working or do you want an efficient solution.
Contributor
Posts: 59

Re: Resolving variable value as a macro variable value

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!

☑ This topic is SOLVED.

Need further help from the community? Please ask a new question.

Discussion stats
  • 12 replies
  • 734 views
  • 1 like
  • 5 in conversation