Below should do what you're asking for.
%let chars=123456789AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz#@;
%let special=#@;
%let id_len=6;
data want(drop=_:);
length id_out $ &id_len;
do _i=1 to &id_len;
_idx=rand('integer',1,%length(&chars));
id_out=cats(id_out,substr("&chars",_idx,1));
end;
do until(_check=3);
_check=0;
/* digit 1 to 9? */
if prxmatch('/\d/',id_out)<1 then
do;
_idx=rand('integer',1,&id_len);
_idy=rand('integer',rank('1'),rank('9'));
substr(id_out, _idx, 1)=byte(_idy);
end;
else _check=sum(_check,1);
/* upper case letter? */
if prxmatch('/[A-Z]/',id_out)<1 then
do;
_idx=rand('integer',1,&id_len);
_idy=rand('integer',rank('A'),rank('Z'));
substr(id_out, _idx, 1)=byte(_idy);
end;
else _check=sum(_check,1);
/* special char? */
if prxmatch("/[&special]/",id_out)<1 then
do;
_idx=rand('integer',1,&id_len);
_idy=rand('integer',1,%length(&special));
substr(id_out, _idx, 1)=substr("&special",_idy,1);
end;
else _check=sum(_check,1);
end;
output;
stop;
run;
proc print;
run;
... View more