我有一个任务,给定一个输入文件,用星号(*)掩码每个信用卡号的前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
,您可以轻松地使用RS
和RT
。
使用-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