BookmarkSubscribeRSS Feed
MAAT
Calcite | Level 5

Hi,

I have a variable that is made up of 15 letters, sometimes less. I have to put that text into string format with a fixed length of 17, left justify it and then pad the leading portion with blank spaces, for those  which are 15 letters or less.

For example:

Var1= AAAAAAA I want to let Var 2 = "AAAAAAA                         "

I need this because I will concatenate variables and I need the blanks, for Example:

Var 2 = "AAAAAAA                         ", Var 3= x, Var 4 = z

I need -----> VarFinally= "AAAAAAA             xz"          

Any suggestion welcome.

Thanks

12 REPLIES 12
stat_sas
Ammonite | Level 13

Hi,

Try this to see if it provides the desired results.

Thanks,

data have;
infile datalines;
input var1 $ 1-9 @10 var2 $1. @12 var3 $1.;
datalines;
AAAA          z x

AAAAAAAA t y
AAAA          r q
AAAAAAA  s e
;

data want;
length var1 $15. varfinal $17.;
set have;
varfinal=left(cat(var1,var2,var3));
run;

MAAT
Calcite | Level 5

Hi, I have already the data set charged and I want to know how I should use the "@" . Maybe making a FORMAT ?

stat_sas
Ammonite | Level 13

Hi,

If you have data then use only

data want;
length var1 $15. varfinal $17.;
set have;
varfinal=left(cat(var1,var2,var3));
run;

Peter_C
Rhodochrosite | Level 12

You asked

MAAT wrote:

Hi, I have already the data set charged and I want to know how I should use the "@" . Maybe making a FORMAT ?

I think the answer might be to use the SUBSTR() function

Tom
Super User Tom
Super User

Perhaps I do not understand the question, but if you have a variable that is 15 characters long and you want to use it to make a new one that is 17 characters long by appending two characters to it why not just do that?

data want ;

  length var1 $15 var2 $17 var3 $1 var4 $1 ;

  set have ;

  var2 = var1 || var3 || var4 ;

run;

Now if for some reason the values in VAR1  have leading blanks that you want to move to the end then use the LEFT() function.

  var2 = left(var1) || var3 || var4 ;

MAAT
Calcite | Level 5

Hi Tom,

That was my first option, but the || doesn´t work with "  " (blanks) if you make  x=Var1||"  "  then x = var1, and it doesn´t solve any! :S

Tom
Super User Tom
Super User

SAS character variables are fixed length.  So you just need to define the variables to have the length that you want.

How did you define the lengths of your variables?  If you just let SAS guess it might not make variables with the lengths that you want. From the words in your original post it looks like you want to define VAR2 with length of $15 and VarFinally with a length of $17.   Looking also at you pseudo code it looks like you should define Var3 and Var4 as length $1.  Length of Var1 does not matter as long as it is less than or equal to VAR2, otherwise assigning a value from var1 into var2 will be truncated.

Check the results of this little test.

data sloppy;

  Var1= 'AAAAAAA';

  Var2= 'AAAAAAA                         ';

  Var3= 'x' ;

  Var4 = 'z' ;

  VarFinally= Var2||Var3||Var4 ;

run;

data neat ;

  length var1 $8 var2 $15 Var3 Var4 $1 VarFinally $17 ;

  Var1= 'AAAAAAA';

  Var2= 'AAAAAAA                         ';

  Var3= 'x' ;

  Var4 = 'z' ;

  VarFinally= Var2||Var3||Var4 ;

run;

proc compare data=sloppy compare=neat;

run;

Tom
Super User Tom
Super User

Actually if the length of X was not previously defined then X=VAR1||' '; would indeed make a variable X with the value of VAR1 padded on the right with one more blank that was already on the end of VAR1.  The length of the new variable X would be defined as the length of the existing variable VAR1 plus one.

SAS variables are fixed length and are always padded with blanks to the full length. (There is no such thing as a VARCHAR() type like you might have in a database system.)

So if VAR1 is of length $10 the following two statements will assign the exact same value to VAR1.

data x;

  length VAR1 $10;

  var1='ABC';

  var1='ABC   ';

Patrick
Opal | Level 21

In SAS character variables are fixed length (padded with blanks). If your variables have already the right length then you only need to left align them before concatenation. Execute below sample code and have a look into the resulting SAS table.

data sample;

  length var1 var2 $17 var_concat $34;

  length syntax_used $50.;

  var1='AAA';

  var2='BBB';

  var_concat=var1||var2;

  syntax_used='var_concat=var1||var2;';

  output;

  var1='  AAA';

  var2='   BBB';

  var_concat=var1||var2;

  syntax_used='var_concat=var1||var2;';

  output;

  var_concat=left(var1||var2);

  syntax_used='var_concat=left(var1||var2);';

  output;

  var_concat=left(var1)||left(var2);

  syntax_used='var_concat=left(var1)||left(var2);';

  output;

  var_concat=cat(left(var1),left(var2));

  syntax_used='var_concat=cat(left(var1),left(var2));';

  output;

  var_concat=put(left(var1),$6.)||put(left(var2),$6.);

  syntax_used='put(left(var1),$6.)||put(left(var2),$6.);';

  output;

  var_concat=substrn(left(var1),1,6)||substrn(left(var1),1,6);

  syntax_used='substrn(left(var1),1,6)||substrn(left(var1),1,6);';

  output;

run;

MAAT
Calcite | Level 5

Hi Patrick, I thing the variables are fixed length but if  I need concatenate after with another variable, SAS "forget" to put the blank fields, and it is the problem! I need the blanks!

RichardinOz
Quartz | Level 8

SAS does not "forget" the trailing blanks.  However, when making a comparison between two character variables as a convenience it in effect trims (removes trailing blanks) for the purpose of making the comparison and only during the comparison.

The alternative would be that you would have to extend the shorter variable with blanks in order to compare two variables of unequal length.  Maybe this is what SAS is doing "under the covers" anyway.  The effect is the same.

This is a convention that has been adopted by SAS and I think they made the right choice.  It would be tedious to have to check the length of each variable before making a comparison, in case the comparison would fail each time the lengths were different.

An alternate design would have used byte(0) ( '00'x ) for padding in which case the number of trailing blanks would not change if the value is copied into a variable with longer length, and would be significant in comparisons.  It's one of the early design decisions that become fundamental to the language.

You can see that SAS retains trailing blanks

data test ;

     length var $ 12 ;

     var = 'ABC' ;

     var = var || 'XYZ' ;

     put var= ;

run ;

Because var is defined with length 12 the value ABC is padded with 9 blanks.  It then has no space left to add on the XYZ.

Macro variables, on the other hand, do not have fixed length and they can be extended, so you get a different result:

%Let var = %Str(ABC         ) ;

%Let var = &var.XYZ ;

%Put &var ;

Richard

Tom
Super User Tom
Super User

If you want to create VarFinally based on the values in VAR1,VAR3 and VAR4 and you have no control over how the lengths of those variables were defined (say you imported them from Excel) then a little defensive coding will make it possible.

data WANT ;

  set HAVE;

  length VarFinally $17. ;

  VarFinally = substr(var1||repeat(' ',15)),1,15)||substr(var3,1)||substr(var4,1);

run;

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 12 replies
  • 6340 views
  • 3 likes
  • 6 in conversation