Why so complicated?
data want;
set have;
do i = 1 to length(mezahe_part);
if substr(mezahe_part,i,1) = "9"
then substr(mezahe_part,i,1) = " ";
else substr(mezahe_part,i,1) = put(sum(1,input(substr(mezahe_part,i,1),1.)),1.);
end;
drop i;
run;
To decode, turn blanks into a 9, zeroes into blanks, otherwise subtract 1.
Why not create a format to mask the last 4 digits without actually changing the underlying value?
May you please show code?
Please note that I need to export the data set into txt file and in the txt file need to see the masked value.
And none of the answers in your previous question here give you already solution approaches?
Are your values numeric or character?
How about providing some examples of what the value currently look like?
Any rules/limits about what the "change" is allowed to do?
I thought about code like that.
Here is the code that is working well, I add 1 to each digit.
Any other shorter suggestions?
Data have;
input MEZAHE_PART;
cards;
9
710
1040
1323
1417
1610
1618
1922
2143
2323
2413
2511
2629
2823
3026
3218
3711
3720
3928
4213
4219
4223
4318
4811
5283
5428
6315
6320
6412
6610
6726
6727
6915
6919
7125
7222
7514
7620
7958
8119
8213
8420
9327
9721
9726
9827
;
Run;
Data want;
set have;
IF substr(cat(MEZAHE_PART),1,1) ne '' then D1=substr(cat(MEZAHE_PART),1,1);else D1='';
IF substr(cat(MEZAHE_PART),2,1) ne '' then D2=substr(cat(MEZAHE_PART),2,1);else D2='';
IF substr(cat(MEZAHE_PART),3,1) ne '' then D3=substr(cat(MEZAHE_PART),3,1);else D3='';
IF substr(cat(MEZAHE_PART),4,1) ne '' then D4=substr(cat(MEZAHE_PART),4,1);else D4='';
D1_b=put(D1,$Mask_Fmt.);
D2_b=put(D2,$Mask_Fmt.);
D3_b=put(D3,$Mask_Fmt.);
D4_b=put(D4,$Mask_Fmt.);
Masked_MEZAHE_PART=CATS(D1_b,D2_b,D3_b,D4_b);
IF substr(cat(Masked_MEZAHE_PART),1,1) ne '' then D1_c=substr(cat(Masked_MEZAHE_PART),1,1);else D1_c='';
IF substr(cat(Masked_MEZAHE_PART),2,1) ne '' then D2_c=substr(cat(Masked_MEZAHE_PART),2,1);else D2_c='';
IF substr(cat(Masked_MEZAHE_PART),3,1) ne '' then D3_c=substr(cat(Masked_MEZAHE_PART),3,1);else D3_c='';
IF substr(cat(Masked_MEZAHE_PART),4,1) ne '' then D4_c=substr(cat(Masked_MEZAHE_PART),4,1);else D4_c='';
D1_d=put(D1_c,$Converted_Back_Mask_Fmt.);
D2_d=put(D2_c,$Converted_Back_Mask_Fmt.);
D3_d=put(D3_c,$Converted_Back_Mask_Fmt.);
D4_d=put(D4_c,$Converted_Back_Mask_Fmt.);
_MEZAHE_PART_=CATS(D1_d,D2_d,D3_d,D4_d);
Drop D1 D2 D3 D4 D1_b D2_b D3_b D4_b D1_c D2_c D3_c D4_c D1_d D2_d D3_d D4_d;
Run;
Using your sample data below one way to go.
data want;
if _n_=1 then
do;
if 0 then masked_value=MEZAHE_PART;
format masked_value z4.;
dcl hash h1();
h1.defineKey('MEZAHE_PART');
h1.defineData('masked_value');
h1.defineDone();
end;
set have;
if h1.find() ne 0 then
do;
masked_value=h1.num_items;
if masked_value=MEZAHE_PART then
do;
masked_value=9999-h1.num_items;
end;
_rc=h1.add();
end;
drop _rc MEZAHE_PART;
run;
An enhanced code sample already shared in your other question referenced earlier.
Why so complicated?
data want;
set have;
do i = 1 to length(mezahe_part);
if substr(mezahe_part,i,1) = "9"
then substr(mezahe_part,i,1) = " ";
else substr(mezahe_part,i,1) = put(sum(1,input(substr(mezahe_part,i,1),1.)),1.);
end;
drop i;
run;
To decode, turn blanks into a 9, zeroes into blanks, otherwise subtract 1.
Thanks,
As I see in your code you run on each digit and perform calculation to get the new digit value.
I have 2 questions please regarding your code:
1- Where in the code you tell SAS to concatenate the digits?
2- Where in the code you tell the name of the new column (I see that the name is mezahe_part)?
data want;
set have;
Before_mask=mezahe_part;
do i = 1 to length(mezahe_part);
if substr(mezahe_part,i,1) = "9" then substr(mezahe_part,i,1) = " ";
else substr(mezahe_part,i,1) = put(sum(1,input(substr(mezahe_part,i,1),1.)),1.);
end;
drop i;
run;
No concatenation needed. The digits are converted in place (through the use of SUBSTR on the left side of the assignment, which is a SAS specific).
Just lovely. A question that asks about "masking" the LAST 4 digits and then the first two examples of values do not have 4 digits and one only has one digit.
So, do you need to add some more details to the requirements?
Values like credit card account numbers or "last 4 of credit card account" really should not be numeric.
I really bet the last 4 digits of the account are not "9". Possibly "0009". And then attempt to process a numeric value with string functions and don't even attempt to control how the string is created from the numeric values.
Just how many "numeric values have been converted to character" notes appear in the log?
@Ronein wrote:
I thought about code like that.
Here is the code that is working well, I add 1 to each digit.
Any other shorter suggestions?
Data have; input MEZAHE_PART; cards; 9 710 1040 1323 1417 1610 1618 1922 2143 2323 2413 2511 2629 2823 3026 3218 3711 3720 3928 4213 4219 4223 4318 4811 5283 5428 6315 6320 6412 6610 6726 6727 6915 6919 7125 7222 7514 7620 7958 8119 8213 8420 9327 9721 9726 9827 ; Run;
@Ronein - You can't store 16 digit credit card numbers accurately in SAS numeric variables because of precision limitations. I just hope you aren't doing this because you will end up with "random" digit changes in the last one or two digits. I deal with credit card numbers all the time and have frequently seen this problem.
Data have;
input MEZAHE_PART;
cards;
9
710
1040
1323
1417
1610
1618
1922
2143
2323
2413
2511
2629
2823
3026
3218
3711
3720
3928
4213
4219
4223
4318
4811
5283
5428
6315
6320
6412
6610
6726
6727
6915
6919
7125
7222
7514
7620
7958
8119
8213
8420
9327
9721
9726
9827
;
Run;
data want;
set have;
length encode $ 20;
temp=put(MEZAHE_PART,best8. -l);
do i=1 to lengthn(temp);
encode=cats(encode,byte(rank( ifc(char(temp,i)='9','/',char(temp,i)) ) + 1));
end;
drop temp i;
run;
data want;
set want;
length decode $ 20;
do i=1 to lengthn(encode);
decode=cats(decode,byte(rank( ifc(char(encode,i)='0',':',char(encode,i)) ) - 1));
end;
drop i;
run;
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
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.