【问题标题】:regex to mask all account numbers in XML up to the last four digits正则表达式将 XML 中的所有帐号屏蔽到最后四位数
【发布时间】:2017-07-03 20:14:02
【问题描述】:

我试图在我的 XML 响应代码中屏蔽所有出现的 AccountNumber。 AccountNumber 有 16 位数字,我想屏蔽前 12 位数字并保留后四位。

XML 响应:

<ns2:PaymentMethod>
  <CCInfo xmlns="">
           <AccountType>sdaj</AccountType>
           <AccountNumber>1234567890123456</AccountNumber>
           <AccountName>sdfsad</AccountName>
           <ExpirationMonth>sdaf</ExpirationMonth>
           <ExpirationYear>afgds</ExpirationYear>
    </CCInfo>
  </ns2:PaymentMethod>
  <ns2:PaymentMethod>
  <CCInfo xmlns="">
           <AccountType>kyfkuk</AccountType>
           <AccountNumber>098765432123987</AccountNumber>
           <AccountName>hjvkv</AccountName>
           <ExpirationMonth>gfdgh</ExpirationMonth>
           <ExpirationYear>tdjk</ExpirationYear>
    </CCInfo>
  </ns2:PaymentMethod>

下面是我的java代码:

String accountNumberPatternString ="<AccountNumber>(^.{12})";
Pattern accountNumberPattern = Pattern.compile(accountNumberPatternString);
Matcher matcher = accountNumberPattern.matcher(data);
String maskedResult = matcher.replaceAll("<AccountNumber>*******");

我期待的结果是:

<AccountNumber>************3456</AccountNumber>

但我得到的结果是:

<AccountNumber>1234567890123456</AccountNumber>

【问题讨论】:

  • 为什么^ 在你的模式中?
  • 一种解决方案是从 xml 中提取 AN。一旦你有了它:你可以使用: String.format("%1$" + AN.length() + "s", AN.subString(13,15).replace(" ","*");跨度>
  • 希望您使用有效的方法将 xml 流转换为字符串,以免损坏过程中的数据。

标签: java regex xml replace


【解决方案1】:

^ 是错误的。如果你只有数字,你也应该只匹配数字与\d() 括号是不必要的。

https://regex101.com/r/Uu6qTR/1

<AccountNumber>\d{12}

【讨论】:

  • 当我使用 String accountNumberPatternString ="\d{12}";我收到错误:无效的转义序列(有效的是 \b \t \n \f \r \" \' \\ )
  • 嗯......当然......你需要双重转义反斜杠,因为它在字符串中。
  • @FlorianPeschka 是对的。 eureka19,尝试使用:\\d{12}
  • @FlorianPeschka 它工作得很好,谢谢。如果帐号的长度不同,会有什么变化。有没有办法说我想屏蔽除最后四位数字之外的整个帐号?这将解决我的可变长度帐号的问题。
  • @eureka19 对于这种情况,我建议您采用汤姆在对您的问题的评论中提到的路线。它在代码中更容易且更少混乱。
【解决方案2】:

我确定您知道dangers of parsing XML with regex,但我们暂时忽略它。

根据您更新的要求,帐号的长度可能会有所不同,我建议使用Matcher.appendReplacement,如下所示:

    Pattern p = Pattern.compile("(?<=<AccountNumber>)\\d*(?=\\d{4})");
    Matcher m = p.matcher(data);
    StringBuffer maskedResult = new StringBuffer();
    while (m.find()) {
        String thisMask = m.group(0).replaceAll(".", "*");
        m.appendReplacement(maskedResult, thisMask);
    }
    m.appendTail(maskedResult);
    System.out.println(maskedResult.toString());

请注意,在上面的示例中,我使用正向后视 (?&lt;=) 来识别帐号的开头,然后正向前瞻 (?=) 以确保保留四位数字。

最后,这是一个更强大的版本,可以处理带有字母、空格和/或破折号的帐号,例如"&lt;AccountNumber&gt; 123 456-78901FFA-56C &lt;/AccountNumber&gt;"

    Pattern p = Pattern.compile("(?<=<AccountNumber>)([-\\s\\w]*)((?:[a-zA-Z0-9][-_\\s]*){4})");
    Matcher m = p.matcher(data);
    StringBuffer maskedResult = new StringBuffer();
    while (m.find()) {
        String thisMask = m.group(1).replaceAll("[^-_\\s]", "*");
        m.appendReplacement(maskedResult, thisMask + "$2");
    }
    m.appendTail(maskedResult);
    System.out.println(maskedResult.toString());

【讨论】:

  • 我在 m.appendReplacement(maskedResult, thisMask); 行中收到以下错误类型 Matcher 中的方法 appendReplacement(StringBuffer, String) 不适用于参数 (StringBuilder, String)
  • @eureka19 哦,对了,对不起。我猜你必须使用 StringBuffer 而不是 StringBuilder。我已经更新了答案。
猜你喜欢
  • 2020-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-14
  • 1970-01-01
相关资源
最近更新 更多