用****掩码输出卡号

  • 本文关键字:掩码 输出 bash sed
  • 更新时间 :
  • 英文 :


我有一个任务,给定一个输入文件,用星号(*)掩码每个信用卡号的前12位数字,并将掩码数字打印到输出文件中。

示例卡号:

1111-2222-3333-4444
4444-3333-2222-1111
1234-5678-9101-1171
1234 5678 9101 1121
7347_9834_7598_2834
8973#9858#3475#8734
2356`7843`0527`5340
8734=7583=4895=7007
8763+2430+6257_9406

一切都应该在shell脚本中完成。

我的解决方案是:

#!/bin/bash
file='cards.txt'
while read data; do
echo $data | sed -r 's/[[:digit:]]{4}/****/;s/[[:digit:]]{4}/****/;s/[[:digit:]]{4}/****/;s/[^0-9,*]+/ /g'
done < $file > cards-masked.txt

关于如何在此任务中使用sed有更好的想法吗?

查看示例数据,似乎您总是有4个数字,由数字以外的字符分隔。

如果你有兴趣使用awk的解决方案,你可以替换所有的数字以外的字符空间。

然后将前3列中的所有字符替换为*

awk '{gsub(/[^0-9]+/, " ");for (i=1;i<4;i++) gsub(/[0-9]/,"*",$i)}1' cards.txt > cards-masked.txt

更易于阅读的版本,并附有简短的解释

awk '{
gsub(/[^0-9]+/, " ")                    # Replace all chars other than 0-9 with a space
for (i=1;i<4;i++) gsub(/[0-9]/,"*",$i)  # Loop the first 3 columns, replace all digits with *
}1' cards.txt > cards-masked.txt          # The 1 evaluates to true, printing the whole line

输出
**** **** **** 4444
**** **** **** 1111
**** **** **** 1171
**** **** **** 1121
**** **** **** 2834
**** **** **** 8734
**** **** **** 5340
**** **** **** 7007
**** **** **** 9406

解决方案1: 使用简单的sed,每次将4位数字替换3次到4*,然后您就全部设置好了。

sed -E 's/[[:digit:]]{4}/****/;s/[[:digit:]]{4}/****/;s/[[:digit:]]{4}/****/' Input_file


解决方案2:对于awk程序,只需使用3倍sub(替代)函数即可完成。

awk '{sub(/[[:digit:]]{4}/,"****");sub(/[[:digit:]]{4}/,"****");sub(/[[:digit:]]{4}/,"****")} 1' Input_file

如果您的输入总是在每4位数字之后有一个非数字分隔符,如问题所示,然后使用gnu-awk,您可以轻松地使用RSRT

使用-v RS='[^0-9]'对非数字字符进行拆分,当记录号不能被4整除时,使用模块将每条记录设置为****。最后,使用ORS=RT,我们将捕获的非数字字符放在输出中,以获得与输入相同的分隔符。

awk -v RS='[^0-9]' 'NR%4 {$0="****"} {ORS=RT} 1' file > output
cat output
****-****-****-4444
****-****-****-1111
****-****-****-1171
**** **** **** 1121
****_****_****_2834
****#****#****#8734
****`****`****`5340
****=****=****=7007
****+****+****_9406

这很简单:

cat cards.txt|rev|sed -e 's/[[:digit:]]/*/5g' |rev > cards-masked.txt
echo "1234-5678-9123-1234"|rev|sed -e 's/[[:digit:]]/*/5g' |rev
****-****-****-1234

这个是反向任务:

cat cards.txt|sed -e 's/[[:digit:]]/*/13g' > cards-masked.txt

正如你所看到的,在while/read循环中也没有必要。每个sed表达式将逐行计算。

这可能适合您(GNU sed):

sed -E '/([0-9]{4}[ #`=+-_]){3}[0-9]{4}/{s//n&n/;h
s/[0-9]/*/g;G;s/.*n(.*)n.*n(.*)n.*n/21/}' file

用换行符将匹配括起来。

复制一份

将所有数字替换为*

添加副本。

使用模式匹配,将原始匹配替换为修改后的匹配。

可以扩展为一行中的多个匹配:

sed -E ':a;/([0-9]{4}[ #`=+-_]){3}[0-9]{4}/{s//n&n/;h
s/[0-9]/*/g;G;s/.*n(.*)n.*n(.*)n.*n/21/;ta}' file

如果只替换前9位数字,使用:

sed -E ':a;/(([0-9]{4}[ #`=+-_]){3})([0-9]{4})/{s//n1n3/;h
s/[0-9]/*/g;G;s/.*n(.*)n.*n(.*)n.*n/21/;ta}' file

替换前15个字符:

sed -e 's/^.{15}/**** **** **** /' < file

输出:

**** **** **** 4444
…
**** **** **** 9406

相同,但保留位置为5、10和15的字符:

sed -e 's/^....(.)....(.)....(.)/****1****2****3/' < file

输出:

****-****-****-4444
…
****+****+****_9406

最新更新