BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.

Hello,
I want to change the special characters using this code.
It's remain to define the size of observation.
the function length does not work
could you, please, help me?

 

 

%macro tt();
data test1;
set test;

%do i=1 %to %sysfunc(length(var));
        lettre=substr(var,&i.,1);
        type=indexc(lettre,'3A3B3C'x);
	if type then do; substr(var,&i.,1)=translate(lettre,'414243'x,'3A3B3C'x);
	end;
	else do; substr(var,&i.,1)=lettre; 
	end;
 %end;    
 run;
%mend;
%tt;

 

 

Whith this method, the code work correctely

 

data test1;
set test;
var1=translate(var,'ABC','3A3B3C'x);
run;

NB: these are tests that I do for myself

Thank you

 

1 ACCEPTED SOLUTION

Accepted Solutions
Kurt_Bremser
Super User

Note that your whole "experimental" logic can be solved without any macro code at all in one simple data step:

data test;
length var $10.;
var = 'test;;:ii<';
output;
var = 'testj;;';
output;
run;

data test1;
set test;
do i = 1 to length(var);
  lettre = substr(var,i,1);
  type = indexc(lettre,'3A3B3C'x);
  if type
  then do;
    substr(var,i,1)=translate(lettre,'414243'x,'3A3B3C'x);
  end;
  else do;
    substr(var,i,1) = lettre; 
  end;
end;
run;

View solution in original post

9 REPLIES 9
andreas_lds
Jade | Level 19

Use

options mprint mlogic symbolgen;

before executing the macro, read the log after execution.

 

The statement

%sysfunc(length(var))

will always return 3, because you don't get the length of the contents of "var", but the length of the text "var".

 

The docs have an interesting chapter about macros.

MichaelLarsen
SAS Employee

What are you trying to accomplish?

 

Do you have characters in column Var that you want to remove?

If yes, you don't need a macro for that, just keep your data step.

 

Do you want to translate the individual characters, ie. one character at a time? then do this instead:

 

var1 = translate(char,'A','3A'x, 'B','3B'x, 'C','3C'x);

 

Just remember that the macro executes before the data step starts, think of a macro as something that generate code statements. 

Kurt_Bremser
Super User

"var" is NOT a macro variable, but probably a data step variable. Its contents are NOT available for macro processing.

 

For the umpteenth time:

The macro PREprocessor is for generating dynamic code, NOT for handling data.

PaigeMiller
Diamond | Level 26

If VAR is indeed a data step variable, DO NOT use macros.

 

%do i=1 %to %sysfunc(length(var));

should be a data step DO loop

 

do i=1 to length(var);

But, we here don't really know what VAR is, you haven't told us.

 

Please note: it is not a good idea to mix and match data step and macro code. While it can be done, you have to be absolutely sure you are performing data step functions on data step variables and macro functions on macro variables; and it should only be done when the data step by itself won't handle the situation without macros.

--
Paige Miller
mansour_ib_sas
Pyrite | Level 9

Hello,

I almost arrived with my solution.
for use correctly the length and the size of each observation, it was necessary to browse one by one.
I say almost because, when the observation size 1 of the variable var is greater than the size of the observation 2, the result in the new table test1 are same size and the processing of the observation 1 is "interrupted" and I do not understand why?

data test;
length var $10.;
var='test;;:ii<';
output;
var='testj;;';
output;
run;


option symbolgen mprint mlogic;

%macro tt();

data  _null_;
set test;
call symputx('nbr', _n_);
run;

%put nbr=&nbr.;
%do j=1 %to &nbr.;


data _null_;
set test(obs=&j.);
call symputx('size', length(var));
run;

data test1;
set  test(obs=&j.);

%do i=1 %to &size.;

%put i=&i;

        lettre=substr(var,&i.,1);
        type  =indexc(lettre,'3A3B3C'x);
       
        if type 
	    then do; substr(var,&i.,1)=translate(lettre,'414243'x,'3A3B3C'x);
	end;
	
        else do; substr(var,&i.,1)=lettre; 
        end;
%end;    
%end;
run;
%mend;

%tt;

Thank you

ErikLund_Jensen
Rhodochrosite | Level 12

Hi mansour_ib_sas

 

It will be a great help if you can give us an example of your wanted output. what should the output in test1 look like? - It seems you are trying to accomplish a relative simple task in a very complicated way that does not utilize the power of SAS.

 

From your example it seems that you examine each single character and translate ; to A, ; to B and < to C. If that is what you want, then the following code will do the job:


data test1; set test;
	var = translate(var,'414243'x,'3A3B3C'x);
run;

Output:

testBBAiiC

testjBB

 

 

 

 

 

 

Kurt_Bremser
Super User

If you want to understand yout own code, you have to write it in a way that makes it easy to read and understand:

%macro tt();

data  _null_;
set test;
call symputx('nbr', _n_);
run;

%put nbr=&nbr.;
%do j = 1 %to &nbr.;

  data _null_;
  set test(obs=&j.);
  call symputx('size', length(var));
  run;

  data test1;
  set test(obs=&j.);
%do i = 1 %to &size.; %put i=&i;
lettre = substr(var,&i.,1); type = indexc(lettre,'3A3B3C'x); if type then do; substr(var,&i.,1)=translate(lettre,'414243'x,'3A3B3C'x); end; else do; substr(var,&i.,1)=lettre; end;
%end; %end;
run;
%mend;

(Hint: do NOT use tabs in code; different systems and users have different tab settings, which skewer the display of code. Replace tabs with blanks, EG has a setting for that)

 

Most of your problems come from a misunderstanding what the obs= dataset option does. It does not read a single observation, but all observations up to the given number.

 

You also repeatedly overwrite test1 in the outer macro loop, so only the results of the last outer loop iteration will take effect. This last iteration is run with the length of the variable in the last observation of test. Since that is the shorter one, you have an incomplete execution of the translate for the first observation that is dealt with in the same step.

 

To determine the number of observations in a dataset, your method is inefficient:

data _null_;
set test;
call symputx('nbr', _n_);
run;

The whole dataset is read, and for every observation, a call symputx is made. If test is empty, no macro variable is created, and subsequent calls to it will fail. Do this instead:

data  _null_;
call symputx('nbr', nobs);
stop;
set test nobs=nobs;
run;

A temporary variable nobs is created by the option of the set statement, and the data step stops immediately after the call symputx, without reading even one observation. OTOH, even with zero observations in the dataset, a correct value is set.

 

 

Bottom line: you still have a very rudimentary understanding of Base SAS code and the data step, so you are WAY out of your depth with dabbling in macro programming. Learn the basics of data step programming first before advancing into macro processing, and DO NOT abuse the macro preprocessor for data handling (which is what you are doing here). You will NOT learn anything useful that way, but only waste your time and ours.

Kurt_Bremser
Super User

Note that your whole "experimental" logic can be solved without any macro code at all in one simple data step:

data test;
length var $10.;
var = 'test;;:ii<';
output;
var = 'testj;;';
output;
run;

data test1;
set test;
do i = 1 to length(var);
  lettre = substr(var,i,1);
  type = indexc(lettre,'3A3B3C'x);
  if type
  then do;
    substr(var,i,1)=translate(lettre,'414243'x,'3A3B3C'x);
  end;
  else do;
    substr(var,i,1) = lettre; 
  end;
end;
run;
mansour_ib_sas
Pyrite | Level 9

Thank You,

Just whith data step, the code work.

I note 

Sincerely

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

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
  • 9 replies
  • 2110 views
  • 4 likes
  • 6 in conversation