【问题标题】:Regular expression using sed使用 sed 的正则表达式
【发布时间】:2010-02-17 17:04:21
【问题描述】:

过去我问过这个问题。但不知何故我没有给出完整的输入。输入是一个日志文件。我正在尝试使用 sed 替换信用卡号的最后四位以外的所有数字。

sed -e :a -e "s/[0-9]\([0-9]\{4\}\)/\*\1/;ta" $today_temp_log

这个表达式确实有效,但它不仅替换了信用卡号码,还替换了一些其他数据(其中数字超过 4)。包含信用卡号的输入记录格式为:

"CARD_NUMBER=[6362229292929290]"

所以我需要替换上面格式的记录。所以上面的记录应该转换为

"CARD_NUMBER=[************9290]"

提前致谢。

【问题讨论】:

标签: regex shell sed


【解决方案1】:

假设信用卡号有 16 位,我会尝试

sed -e :a -e "s/[0-9]\{12\}\([0-9]\{4\}\)/\*\*\*\*\*\*\*\*\*\*\*\*\1/;ta" $today_temp_log

【讨论】:

  • 已编辑(甚至测试)。谢谢,KennyTM
  • 谢谢。信用卡号从 12 到 19 不等(来自维基百科!)。所以这只适用于 16?
【解决方案2】:
sed -e :a -e "s/\(CARD_NUMBER=\[\**\)[0-9]\([0-9]\{4\}\)/\1\*\2/;ta"

测试用例:

$ echo "blah=[123456789012345678] CARD_NUMBER=[6362229292929290] CARD_NUMBER=[13456]" | sed -e :a -e "s/\(CARD_NUMBER=\[\**\)[0-9]\([0-9]\{4\}\)/\1\*\2/;ta"
blah=[123456789012345678] CARD_NUMBER=[************9290] CARD_NUMBER=[*3456]

【讨论】:

  • 谢谢。这行得通。我理解除了“[**)”部分的表达。
  • @user: \[ 匹配左方括号,\\** 匹配零个或多个星,\) 是捕获组的结尾。
【解决方案3】:
var1="CARD_NUMBER=[6362229292929290]"
IFS="="
set -- $var1
cardnumber=$2
result=$(echo $cardnumber | awk 'BEGIN{OFS=FS=""}{for(i=1;i<=NF-5 ;i++){ $i="*"} }1')
echo "$1=[$result"

输出

$ ./shell.sh
CARD_NUMBER=[*************9290]

或者用awk

var1="CARD_NUMBER=[6362229292929290]"
echo $var1 | awk 'BEGIN{ OFS=FS="=" }
{
    gsub(/\[|\]/,"",$2)
    m=split($2,s,"")
    for(i=1;i<=m-4;i++){ s[i]="*" }
    str=$1 OFS "["
    for(i=1;i<=m;i++){ str=str s[i] }
    str=str "]"
}END{ print str } '

输出

$ ./shell.sh
CARD_NUMBER=[************9290]

以上适用于任何数字长度的卡号

【讨论】:

    【解决方案4】:

    根据我的回答here,这将掩盖号码的开头,并为几乎任何位数的卡号留下标签、括号和最后四位:

    sed -e 'h' -e 's/.*\([0-9]\{4\}\)/\1/' -e 'x' -e 's/\(.*\[\)\([0-9]*\)\([0-9]\{4\}\)./\1\2/' -e 's/[0-9]/*/g' -e 'G' -e 's/\n//'
    

    如果您需要验证总位数是否仅在给定范围内,也可以这样做。

    编辑:

    这里有几种方法:

    通过太长或太短的数字不变:

    sed -e '/.*\[[0-9]\{12,19\}\]/!b' -e 'h' -e 's/.*\([0-9]\{4\}\)/\1/' -e 'x' -e 's/\(.*\[\)\([0-9]*\)\([0-9]\{4\}\)./\1\2/' -e 's/[0-9]/*/g' -e 'G' -e 's/\n//'
    
    CARD_NUMBER=[12345678] 产生 CARD_NUMBER=[12345678] CARD_NUMBER=[123456789012] 产生 CARD_NUMBER=[********9012] CARD_NUMBER=[12345678901234567890] 产生 CARD_NUMBER=[12345678901234567890]

    使用不同的屏蔽字符屏蔽所有过长或过短的数字:

    sed -e '/.*\[[0-9]\{12,19\}\]/!{s/[0-9]/x/g;b}' -e 'h' -e 's/.*\([0-9]\{4\}\)/\1/' -e 'x' -e 's/\(.*\[\)\([0-9]*\)\([0-9]\{4\}\)./\1\2/' -e 's/[0-9]/*/g' -e 'G' -e 's/\n//'
    
    CARD_NUMBER=[12345678] 产生 CARD_NUMBER=[xxxxxxxx] CARD_NUMBER=[123456789012] 产生 CARD_NUMBER=[********9012] CARD_NUMBER=[12345678901234567890] 产生 CARD_NUMBER=[xxxxxxxxxxxxxxxxxxxx]

    【讨论】:

    • 谢谢。数字是从 12 到 19。
    【解决方案5】:

    您可以使用 sed 中的地址字段将替换限制为匹配特定模式的行。因此,只需将/CARD_NUMBER=/ 添加到表达式的开头,即可得到

    sed -e :a -e "/CARD_NUMBER=/s/[0-9]\([0-9]\{4\}\)/\*\1/;ta" $today_temp_log
    

    【讨论】:

      猜你喜欢
      • 2018-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-03
      • 2017-07-28
      • 1970-01-01
      • 1970-01-01
      • 2010-09-19
      相关资源
      最近更新 更多