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

Dear experts,

 

I have a query on how to dynamically interchange the position of a character variable in a way that receiver of my file can re-generate the original values.

 

Sample Input and Output is as follows:

InputOutput
MichaelLhameci
Jack@gmail.comkcja@gmail.com
AO987JJ9J78JOA
96502345676953035947

 

Thanks in advance..

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
PGStats
Opal | Level 21

You can permute the string characters following a random sequence set by a secret seed, and then reverse the permutation using the same seed:

 

data have;
input InputStr :$20.;
datalines; 
Michael
Jack@gmail.com
AO987JJ
9650234567
;

%let seed=736435; /* Secret code */

/* Blurring the strings */
data blur;
retain seed &seed.;
set have;
isEmail = index(InputStr, "@") > 1;
length str $20;
if isEmail then str = scan(InputStr,1,"@");
    else str = InputStr;
isName = str = propCase(str);

array pos{20};
do i = 1 to length(str);
    pos{i} = i;
    end;
  
/* Could be coded with a macro I guess, to accomodate longer strings ... */
select (length(str));
when ( 2) call ranperm(seed, of pos1-pos2);
when ( 3) call ranperm(seed, of pos1-pos3);
when ( 4) call ranperm(seed, of pos1-pos4);
when ( 5) call ranperm(seed, of pos1-pos5);
when ( 6) call ranperm(seed, of pos1-pos6);
when ( 7) call ranperm(seed, of pos1-pos7);
when ( 8) call ranperm(seed, of pos1-pos8);
when ( 9) call ranperm(seed, of pos1-pos9);
when (10) call ranperm(seed, of pos1-pos10);
when (11) call ranperm(seed, of pos1-pos11);
when (12) call ranperm(seed, of pos1-pos12);
when (13) call ranperm(seed, of pos1-pos13);
when (14) call ranperm(seed, of pos1-pos14);
when (15) call ranperm(seed, of pos1-pos15);
when (16) call ranperm(seed, of pos1-pos16);
when (17) call ranperm(seed, of pos1-pos17);
when (18) call ranperm(seed, of pos1-pos18);
when (19) call ranperm(seed, of pos1-pos19);
when (20) call ranperm(seed, of pos1-pos20);
otherwise;
end;

length OutputStr $20;
do i = 1 to length(str);
    substr(outputStr, i, 1) = substr(str, pos{i}, 1);
    end;
    
if isName then OutputStr = propCase(OutputStr);
if isEmail then OutputStr = catx("@", OutputStr, scan(InputStr, 2, "@"));
drop i seed isName isEmail str pos:;
run;

/* Recovering the strings, using the same secret code */
data want;
retain seed &seed.;
set blur;
isEmail = index(OutputStr, "@") > 1;
length str $20;
if isEmail then str = scan(OutputStr,1,"@");
    else str = OutputStr;
isName = str = propCase(str);

array pos{20};
do i = 1 to length(str);
    pos{i} = i;
    end;
  
select (length(str));
when ( 2) call ranperm(seed, of pos1-pos2);
when ( 3) call ranperm(seed, of pos1-pos3);
when ( 4) call ranperm(seed, of pos1-pos4);
when ( 5) call ranperm(seed, of pos1-pos5);
when ( 6) call ranperm(seed, of pos1-pos6);
when ( 7) call ranperm(seed, of pos1-pos7);
when ( 8) call ranperm(seed, of pos1-pos8);
when ( 9) call ranperm(seed, of pos1-pos9);
when (10) call ranperm(seed, of pos1-pos10);
when (11) call ranperm(seed, of pos1-pos11);
when (12) call ranperm(seed, of pos1-pos12);
when (13) call ranperm(seed, of pos1-pos13);
when (14) call ranperm(seed, of pos1-pos14);
when (15) call ranperm(seed, of pos1-pos15);
when (16) call ranperm(seed, of pos1-pos16);
when (17) call ranperm(seed, of pos1-pos17);
when (18) call ranperm(seed, of pos1-pos18);
when (19) call ranperm(seed, of pos1-pos19);
when (20) call ranperm(seed, of pos1-pos20);
otherwise;
end;

length SecretStr $20;
do i = 1 to length(str);
    substr(SecretStr, pos{i}, 1) = substr(str, i, 1);
    end;
    
if isName then SecretStr = propCase(SecretStr);
if isEmail then SecretStr = catx("@", SecretStr, scan(OutputStr, 2, "@"));
drop i seed isName isEmail str pos:;
run;

title "Blurred and deblurred strings";
proc print data=want; run;
            Blurred and deblurred strings
Obs. 	InputStr 	OutputStr 	SecretStr
1 	Michael 	Acemhil 	Michael
2 	Jack@gmail.com 	Cjak@gmail.com 	Jack@gmail.com
3 	AO987JJ 	78AO9JJ 	AO987JJ
4 	9650234567 	4620673559 	9650234567
PG

View solution in original post

5 REPLIES 5
ballardw
Super User

How many other exceptions to scrambling the entire string do you have? And what do they look like if they are not email addresses?

 

Do you mean a random approach?

 

And where did the second J go in your third example? If characters are to be substituted you need to state any rules involved.

 

How do you expect the other person to use this?

Trishjais
Obsidian | Level 7
Hello
There could be only 4 types, mobile number, email addresses, ID type(SSN),Full Name.
I want to just change the position of character on the basis of length of each variable. For eg JACK has length of 4 so the receiver of my file will re-arrange the characters to get JACK, similarly for email addresses any character before @ should be interchanged.
SASKiwi
PROC Star

What is your actual business problem? Also interchanging character positions isn't masking, it is a very basic form of encryption. If you simply want to exchange data with other parties in encrypted form, why not just use an encryption tool? It is so much easier than doing what you are suggesting and a whole lot more secure too.

PGStats
Opal | Level 21

You can permute the string characters following a random sequence set by a secret seed, and then reverse the permutation using the same seed:

 

data have;
input InputStr :$20.;
datalines; 
Michael
Jack@gmail.com
AO987JJ
9650234567
;

%let seed=736435; /* Secret code */

/* Blurring the strings */
data blur;
retain seed &seed.;
set have;
isEmail = index(InputStr, "@") > 1;
length str $20;
if isEmail then str = scan(InputStr,1,"@");
    else str = InputStr;
isName = str = propCase(str);

array pos{20};
do i = 1 to length(str);
    pos{i} = i;
    end;
  
/* Could be coded with a macro I guess, to accomodate longer strings ... */
select (length(str));
when ( 2) call ranperm(seed, of pos1-pos2);
when ( 3) call ranperm(seed, of pos1-pos3);
when ( 4) call ranperm(seed, of pos1-pos4);
when ( 5) call ranperm(seed, of pos1-pos5);
when ( 6) call ranperm(seed, of pos1-pos6);
when ( 7) call ranperm(seed, of pos1-pos7);
when ( 8) call ranperm(seed, of pos1-pos8);
when ( 9) call ranperm(seed, of pos1-pos9);
when (10) call ranperm(seed, of pos1-pos10);
when (11) call ranperm(seed, of pos1-pos11);
when (12) call ranperm(seed, of pos1-pos12);
when (13) call ranperm(seed, of pos1-pos13);
when (14) call ranperm(seed, of pos1-pos14);
when (15) call ranperm(seed, of pos1-pos15);
when (16) call ranperm(seed, of pos1-pos16);
when (17) call ranperm(seed, of pos1-pos17);
when (18) call ranperm(seed, of pos1-pos18);
when (19) call ranperm(seed, of pos1-pos19);
when (20) call ranperm(seed, of pos1-pos20);
otherwise;
end;

length OutputStr $20;
do i = 1 to length(str);
    substr(outputStr, i, 1) = substr(str, pos{i}, 1);
    end;
    
if isName then OutputStr = propCase(OutputStr);
if isEmail then OutputStr = catx("@", OutputStr, scan(InputStr, 2, "@"));
drop i seed isName isEmail str pos:;
run;

/* Recovering the strings, using the same secret code */
data want;
retain seed &seed.;
set blur;
isEmail = index(OutputStr, "@") > 1;
length str $20;
if isEmail then str = scan(OutputStr,1,"@");
    else str = OutputStr;
isName = str = propCase(str);

array pos{20};
do i = 1 to length(str);
    pos{i} = i;
    end;
  
select (length(str));
when ( 2) call ranperm(seed, of pos1-pos2);
when ( 3) call ranperm(seed, of pos1-pos3);
when ( 4) call ranperm(seed, of pos1-pos4);
when ( 5) call ranperm(seed, of pos1-pos5);
when ( 6) call ranperm(seed, of pos1-pos6);
when ( 7) call ranperm(seed, of pos1-pos7);
when ( 8) call ranperm(seed, of pos1-pos8);
when ( 9) call ranperm(seed, of pos1-pos9);
when (10) call ranperm(seed, of pos1-pos10);
when (11) call ranperm(seed, of pos1-pos11);
when (12) call ranperm(seed, of pos1-pos12);
when (13) call ranperm(seed, of pos1-pos13);
when (14) call ranperm(seed, of pos1-pos14);
when (15) call ranperm(seed, of pos1-pos15);
when (16) call ranperm(seed, of pos1-pos16);
when (17) call ranperm(seed, of pos1-pos17);
when (18) call ranperm(seed, of pos1-pos18);
when (19) call ranperm(seed, of pos1-pos19);
when (20) call ranperm(seed, of pos1-pos20);
otherwise;
end;

length SecretStr $20;
do i = 1 to length(str);
    substr(SecretStr, pos{i}, 1) = substr(str, i, 1);
    end;
    
if isName then SecretStr = propCase(SecretStr);
if isEmail then SecretStr = catx("@", SecretStr, scan(OutputStr, 2, "@"));
drop i seed isName isEmail str pos:;
run;

title "Blurred and deblurred strings";
proc print data=want; run;
            Blurred and deblurred strings
Obs. 	InputStr 	OutputStr 	SecretStr
1 	Michael 	Acemhil 	Michael
2 	Jack@gmail.com 	Cjak@gmail.com 	Jack@gmail.com
3 	AO987JJ 	78AO9JJ 	AO987JJ
4 	9650234567 	4620673559 	9650234567
PG
Trishjais
Obsidian | Level 7
Thank . It was really helpful.

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!

Mastering the WHERE Clause in PROC SQL

SAS' Charu Shankar shares her PROC SQL expertise by showing you how to master the WHERE clause using real winter weather data.

Find more tutorials on the SAS Users YouTube channel.

Discussion stats
  • 5 replies
  • 557 views
  • 2 likes
  • 4 in conversation