BookmarkSubscribeRSS Feed
deleted_user
Not applicable
I would like to create a macro that would create a sort variable for a dotted decimal string (Chap: 1.2.3.4 or IP: 192.168.1.101) so that, for example, 1.10.1 would appear after 1.2.1 .

I was unable to find anything similar in the forums.

I can do this in Base SAS, but don't remember how to pass a data step variable into a macro.

I created the test data set with:

data test ;
input chapter $ ;
cards;
1.2.2.5
1.2.10.5
2.10
1.35
1.2.5
2.587
2.3.9.8
run ;

I created the data step version as:

data test1 ;
set test ;
array part{5} $3 ;
length chapters $19 ;
do i= 1 to countc(chapter,".")+1 ;
part(i)=scan(chapter,i);
part(i)=translate(right(part(i)),"0"," ");
chapters=trim(chapters)||"."||part(i);
end;
chapters=substr(chapters,3);
run ;

(the output gives a clearer idea of where I'm heading with this)

I created a macro that almost does what I'm looking for:

%macro multidec(string);
%local part sect padc ;
%let part=1 ;
%let sect = %scan(&string, ∂) ;
%let padc=00 ;
%let mult= ;
%do %while(§ ne );
%let sect=%substr(&padc§,%length(§)) ;
%let mult=&mult..§ ;
%let part=%eval(∂ + 1);
%let sect=%scan(&string, ∂) ;
%end;
%let mult=%substr(&mult,2) ;
%put &mult ;
%mend ;
%multidec(1.2.3.4) ;

Where I hang up is passing the value of chapter (1.2.3.4) into a macro. I'd like to pass in variable name from a dataset as well as the name of the new variable to be created, something like %multidec(chapter,chapters).

Any suggestions you'd care to offer would be welcome. Especially if someone has already done this ...
3 REPLIES 3
data_null__
Jade | Level 19
I have done this from time to time. I find it is easier to create sort variableS one for each dot so to speak. You sort by these variables and display the original.

[pre]
data test;
input chapter $;
array s[4];
length w $32;
drop w;
do _n_ = 1 to dim(s);
w = scan(chapter,_n_);
if missing(w) then leave;
s[_n_] = input(w,comma32.);
end;
cards;
1.2.2.5
1.2.10.5
2.10
1.35
1.2.5
2.587
2.3.9.8
;;;;
run;
proc sort;
by s:;
run;
proc print;
run;
[/pre]

[pre]
Obs chapter s1 s2 s3 s4

1 1.2.2.5 1 2 2 5
2 1.2.5 1 2 5 .
3 1.2.10.5 1 2 10 5
4 1.35 1 35 . .
5 2.3.9.8 2 3 9 8
6 2.10 2 10 . .
7 2.587 2 587 . .
[/pre]
deleted_user
Not applicable
Thanks _null_.

I was hoping to collapse the 'part's but thank you.

I also learned something new from your example that was quite valuable.

I did not know I could sort with a by 's:' which apparently uses all the components of the array 's'. Thanks for that.
data_null__
Jade | Level 19
You can combine the parts but then you have to have leading zeros or blanks and that gets you right back where you started.

"P:" is called a "SAS Variable Lists". There are a number of ways to specify an SVL including the nameroot followed by the colon. The SVL is very powerful. Look in the docuemention for a complete and detailed description. You can use the SVL in data steps and most procs. It is interesting to me that you can use something like P: or even _ALL_ in a DEFINE statement in PROC REPORT but you can NOT use a list of variables like "p1 p2 p3".

An array in SAS only exist in a data step. It is a fancy way to refer to a list of variables with in INDEX. A subtle difference from other programming languages but important.

SAS Innovate 2025: Register Now

Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!

How to Concatenate Values

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 3 replies
  • 1373 views
  • 0 likes
  • 2 in conversation