BookmarkSubscribeRSS Feed
varmal
Calcite | Level 5

 

hi All,

can some please help me to get the desired data, I want number from 123456789101 to like this :1234-5678-9101....??

data a;
input number;
value=substr(number,1,4)||'-'||substr(number,5,7)||'-'||substr(number,8);
cards;
123456789101
;run;

thanks 

 

11 REPLIES 11
novinosrin
Tourmaline | Level 20
proc format;
picture num
low-high ='9999-9999-9999';
run;


data a;
input number;
value=put(number,num.);
cards;
123456789101
;run;
novinosrin
Tourmaline | Level 20
data a;
input number;
array t(3) $4 _temporary_;
call pokelong(put(number,best12.),addrlong(t(1)),12);
value=catx('-',of t(*));
cards;
123456789101
;run;
hashman
Ammonite | Level 13

@varmal:

Your own attempt would work if you executed it a bit more diligently:

data a (drop = _:) ;                                                         
  input number ;                                                             
  _c = put (number, z12.) ;                                                  
  value = substr (_c,1,4) || '-' || substr (_c,5,4) || '-' || substr (_c,9) ;
  cards ;                                                                    
123456789101                                                                 
;                                                                            
run ;                                                                        

_C prevents the step from generating data type conversion notes. Alternatively, you can use a loop to save some keystrokes:

data a ;                                                                                                                                
  input number ;                                                                                                                        
  length value $ 14 ;                                                                                                                   
  do _n_ = 1, 5, 9 ;                                                                                                                    
    value = catx ("-", value, substr (put (number, z12.), _n_, 4)) ;                                                                    
  end ;                                                                                                                                 
  put value= ;                                                                                                                          
  cards ;                                                                                                                               
123456789101                                                                                                                            
;                                                                                                                                       
run ;                                                         

Having said that, I think that the picture format approach offered by @novinosrin is a neater solution.

 

Kind regards

Paul D.

 

PeterClemmensen
Tourmaline | Level 20
data _null_;
	x=123456789101;
	y=prxchange('s/(\d{4})(\d{4})(\d{4})/$1-$2-$3/', -1, x);
	put y=;
run;
hashman
Ammonite | Level 13

@PeterClemmensen:

Wow. I admire your ability to put this kind of expression together.

But frankly, @novinosrin's picture format 9999-9999-9999 looks much more self-explanatory to me, plus it doesn't generate implicit data type conversion notes in the log.

 

Kind regards

Paul D.

   

PeterClemmensen
Tourmaline | Level 20

@hashman I could not agree more, picture formats are the way to go here 🙂

VinitvictorCorr
Quartz | Level 8

If the length of the number is not known, you can use the below code:

In your case its 12 so it would be much simpler

 

 

data a(keep=s z);
s="123456789";
%macro nums;
c=length(s);
call symput('p',put(c,best.));
l=int(c/4);
call symput('k',put(l,best.));
%do i=1 %to &k.;
%if &i.=1 %then %do;
a&i.=substr(s,1,4);
%end;
%if &i. ne 1 %then %do;
a&i.=substr(s,(&i.-1)*4+1,4);
%end;
%if &i.=&k. %then %do;
%let m=%sysevalf(&k.+1,integer);
%put &m.;
a&m.=substr(s,(&i)*4+1);
%end;
%end;
length z $%sysevalf(&p.+&m.,integer).;
%do j=1 %to &m.;
%if &j.=1 %then %do;
z=a&j.;
%end;
%else %do;
z=cats(z,"-",trim(a&j.));
%end;
%end;
%mend nums;
%nums;
run;

hashman
Ammonite | Level 13

@VinitvictorCorr:

1. I'd suggest that you test your solution before posting it:

  • Did you notice that it doesn't work since the macro variable K that is supposed to be populated by SYMPUT is not resolved when it's dereferenced as the upper bound of the %DO loop?    
  • How do you expect K - and P - to be populated by the SYMPUT call, active only during the DATA step run time, during the macro execution time that occurs earlier? Note that just because you coded the macro inside the DATA step doesn't change this behavior.

2. If your intent is to set the length of the character variable Z based on the number of digits in the digit string S determined at run time - or any other quantity determined at run time - it cannot be done because it is set at compile time; and the DATA step is not a time machine. You can only set the length of Z to the length of S by assigning Z=S, but then you won't have enough room for the intervening dashes.   

 

3. Under the OP's conditions, the input variable NUMBER is a numeric variable whose value is integer. Even if setting the length of the "dashed" output string were possible at run time - say, based on the expression ceil(log10(number)), - it would be a wasted effort since the integer precision of a SAS numeric variable is limited to 15 digits under ASCII and 16 under EBCDIC, which means that under no circumstances you can have more than 3 dashes separating every 4 consecutive digits.      

 

Kind regards

Paul D.

VinitvictorCorr
Quartz | Level 8
i tested the program before posting it and it worked fine. i dont see why it would generate an issue at your end.. in my code i made sure that whatever the length of the input string, the output string would have extra length, that too the number of - in it. so if your sting is 12 chars long, the output string will be 15 chars long
VinitvictorCorr
Quartz | Level 8

sorry my bad.. @hashman 😛 . Got what you wanted to say. I tweeked it a bit. I think this will work now

 

 

data a(keep=s z);
s="123456789";
%macro nums;
c=length(s);
c1=put(c,best.);
call symput('p',c1);
l=int(c/4);
l1=put(l,best.);
call symput('k',l1);
%do i=1 %to &k.;
%if &i.=1 %then %do;
a&i.=substr(s,1,4);
%end;
%if &i. ne 1 %then %do;
a&i.=substr(s,(&i.-1)*4+1,4);
%end;
%if &i.=&k. %then %do;
%let m=%sysevalf(&k.+1,integer);
%put &m.;
a&m.=substr(s,(&i)*4+1);
%end;
%end;
length z $%sysevalf(&p.+&m.,integer).;
%do j=1 %to &m.;
%if &j.=1 %then %do;
z=a&j.;
%end;
%else %do;
z=cats(z,"-",trim(a&j.));
%end;
%end;
%mend nums;
%nums;
run;

 

 

Please let me know if this works 🙂

SAS Innovate 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

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
  • 11 replies
  • 2359 views
  • 7 likes
  • 6 in conversation