🔒 This topic is solved and locked.
Need further help from the community? Please
sign in and ask a new question.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Posted 07-17-2020 10:51 PM
(986 views)
Hello SAS friends, I am new to SAS and I am still learning. I am in need of a program that generates a random ID. I found a script on this forum and made a few changes and it works, but it is not quite what I need. I need this script to force the random generating ID to Always use at least 1 upper case letter, 1 number and 1 special character (# or @). Is this possible? Here is the code I am using.
data temp (keep=id_out); allowed="123456789AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz#@"; num_ids=1; idlen=8; array done{100} $200.; length my_id $6; num_allowed=length(strip(allowed)); i=1; do until (i=num_ids+1); do j=1 to 6; temp=ceil((num_allowed * rand("uniform"))); substr(my_id,j,1)=substr(allowed,temp,1); end; if whichc(my_id,of done{*})=0 then do; done{i}=my_id; i=i+1; id_out=my_id; output; end; end; run;
Any help would be great!
1 ACCEPTED SOLUTION
Accepted Solutions
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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;
2 REPLIES 2
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
I would first select in order 1 random uppercase, 1 random number, 1 random special character, 5 random any characters as array elements e.g. c1-c8. Then randomly sort the array and assign the id by concatenating c1-c8 after randomization. There are many ways to do this in SAS. This approach guarantees your requirements (1 each of the given categories and 8 total).
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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;