【问题标题】:java regex mask all elements in a list with last 4 characters visiblejava正则表达式屏蔽列表中的所有元素,最后4个字符可见
【发布时间】:2021-02-21 08:26:01
【问题描述】:

我有一个如下的字母数字字符串列表

["nG5wnyPVNxS6PbbDNNbRsK5zanG94Et6Q4y74","GgQoDWqP7KtxXeePyyebu5EnNp8XxPC1odeNv","GgQoDWqP7KtxXeePyyebu5EnNp8XxPC1o12NN"]

我需要屏蔽所有最后 4 个字符可见的元素,并且 [ " 不能被屏蔽如下。

["XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX4y74","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXdeNv","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX12NN"]

我尝试过使用

(\\W+)(\\W+)(\\w+)(\\w+)(\\w+)(\\w+)(\\w+)(\\W+)(\\W+) 

作为键和 $1$2XXXXXXXXXX$4$5$6$7$8$9 作为值

maskedValue = maskedValue.replaceAll("(\\W+)(\\W+)(\\w+)(\\w+)(\\w+)(\\w+)(\\w+)(\\W+)(\\W+)", "$1$2XXXXXXXXXX$4$5$6$7$8$9")

但这只是掩盖了第一个元素。

["XXXXXXXXXXdeNv","nG5wnyPVNxS6PbbDNNbRsK5zanG94Et6Q4y74"]

感谢任何潜在客户。提前致谢。

【问题讨论】:

  • 您可以在字符串\w(?=\w*\w{4}$) 的末尾匹配一个断言4 个单词字符的单词字符并替换为X regex101.com/r/xY73eY/1
  • 嗨,保罗,谢谢您的信息。我已经尝试过了。这里的问题是,上面的正则表达式只匹配一个元素。字符串输入 = "[\"nG5wnyPVNxS6PbbDNNbRsK5zanG94Et6Q4y74\",\"GgQoDWqP7KtxXeePyyebu5EnNp8XxPC1odeNv\",\"GgQoDWqP7KtxXeePyyebu5EnNp8XxPC1o12NN\"]";布尔有效 = input.matches("\\w(?=\\w*\\w{4}$)");这返回 false,因为它与元素列表不匹配。
  • 任何答案对你有用吗?
  • 如果我必须使用自己的实现进行屏蔽,所有提到的建议都有效。在这里,我必须使用第三方定义的方式,只传递一个与我的字符串匹配的正则表达式 ((\\W+)(\\W+)(\\w+)(\\w+)(\\w+) (\\w+)(\\w+)(\\W+)(\\W+)) 和一种格式,他们应该以哪种方式屏蔽它($1$2XXXXXXXXXX$4$5$6$7$8$9)。我需要一种类似于下面代码行的方法。 maskedValue = maskedValue.replaceAll("(\\W+)(\\W+)(\\w+)(\\w+)(\\w+)(\\w+)(\\w+)(\\W+)(\\ W+)", "$1$2XXXXXXXXXX$4$5$6$7$8$9");

标签: java regex masking


【解决方案1】:

对于单个值,您可以使用断言来匹配在字符串末尾断言 4 个字符的单词字符。

\w(?=\w*\w{4}$)

Regex demo | Java demo

String values[] = {"nG5wnyPVNxS6PbbDNNbRsK5zanG94Et6Q4y74","GgQoDWqP7KtxXeePyyebu5EnNp8XxPC1odeNv","GgQoDWqP7KtxXeePyyebu5EnNp8XxPC1o12NN"};
for (String element : values)
    System.out.println(element.replaceAll("\\w(?=\\w*\\w{4}$)", "X"));

输出

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX4y74
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXdeNv
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX12NN

对于整个字符串,您可以在正向回溯中使用有限量词来匹配开头的",后跟多个单词字符。然后匹配结束"之前有4个字符的所有字符

"(?<=\"{0,100})\\w(?=\\w*\\w{4}\")"

Regex demo | Java demo

String regex = "(?<=\"{0,100})\\w(?=\\w*\\w{4}\")";
String string = "[\"nG5wnyPVNxS6PbbDNNbRsK5zanG94Et6Q4y74\",\"GgQoDWqP7KtxXeePyyebu5EnNp8XxPC1odeNv\",\"GgQoDWqP7KtxXeePyyebu5EnNp8XxPC1o12NN\"] ";
System.out.println(string.replaceAll(regex, "X"));

输出

["XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX4y74","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXdeNv","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX12NN"] 

【讨论】:

  • 整个 ["nG5wnyPVNxS6PbbDNNbRsK5zanG94Et6Q4y74","GgQoDWqP7KtxXeePyyebu5EnNp8XxPC1odeNv","GgQoDWqP7KtxXeePyyebu5EnNp8XxPC1o12NN"] 是一个 json 响应的一部分,应该被视为一个字符串。我不应该用 [ " list of elements " ] 标记或拆分此字符串
  • @RamaKrishnaRajuGVSS 将其解析为 json 会更好,但我添加了另一个选项来获取除最后 4 个字符之外的所有掩码。
  • 如果我必须使用自己的实现进行屏蔽,所有提到的建议都有效。在这里,我必须使用第三方定义的方式,只传递一个与我的字符串匹配的正则表达式 ((\\W+)(\\W+)(\\w+)(\\w+)(\\w+) (\\w+)(\\w+)(\\W+)(\\W+)) 和一种格式,他们应该以哪种方式屏蔽它($1$2XXXXXXXXXX$4$5$6$7$8$9)。我需要一种类似于下面代码行的方法。 maskedValue = maskedValue.replaceAll("(\\W+)(\\W+)(\\w+)(\\w+)(\\w+)(\\w+)(\\w+)(\\W+)(\\ W+)", "$1$2XXXXXXXXXX$4$5$6$7$8$9");
【解决方案2】:

使用流:

List<String> terms = Arrays.asList(new String[] {
    "nG5wnyPVNxS6PbbDNNbRsK5zanG94Et6Q4y74",
    "GgQoDWqP7KtxXeePyyebu5EnNp8XxPC1odeNv",
    "GgQoDWqP7KtxXeePyyebu5EnNp8XxPC1o12NN"
});
List<String> termsOut = terms.stream()
    .map(t -> String.join("", Collections.nCopies(t.length() - 4, "x")) +
              t.substring(t.length() - 4))
    .collect(Collectors.toList());
System.out.println(termsOut);

打印出来:

[xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx4y74,
 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxdeNv, 
 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx12NN]

请注意,此解决方案甚至不使用正则表达式,这意味着它可能优于基于正则表达式的解决方案。

【讨论】:

  • 整个 ["nG5wnyPVNxS6PbbDNNbRsK5zanG94Et6Q4y74","GgQoDWqP7KtxXeePyyebu5EnNp8XxPC1odeNv","GgQoDWqP7KtxXeePyyebu5EnNp8XxPC1o12NN"] 是 json 响应的一部分,应该是
  • 然后将 JSON 数组解析成 Java 集合。我不明白这个问题。
  • 我完全同意你的 cmets 但是我的情况下的掩蔽是通过第三方 jar 来处理的,我应该将属性传递给如下 key:\\"accountIdList\\"[\ \s]*\\:[\\s]*(\\W+)(\\W+)(\\w+)(\\w+)(\\w+)(\\w+)(\\w+)(\ \W+)(\\W+) mask:\\"accountIdList\\":$1$2XXXXXXXXXX$4$5$6$7$8$9 第三方 jar 中的掩码将由这些属性使用 java replaceAll 方法处理。
【解决方案3】:

假设每个字符串都以引号开头和结尾

算法:

使用标志或堆栈数据结构来了解它是起始引用还是结束引用。 例如: 遍历字符串。最初标志将为假。当您遇到新的报价时,您必须翻转标志并继续遍历,直到找到其他报价。你可以这样做 栈栈 = 新栈();

示例工作流程:

String str="random";
    
boolean flag = false;
int idx = 0;
List<Pair<Integer, Integer>> indices = new ArrayList<>();
StringBuilder string = new StringBuilder(); // for final string
int start;
int end;
    
while(idx < str.length()){
    
    if (str.charAt(idx) == '"' && !flag){
    // start index of string
    string.append(s.charAt(idx));
    start = idx;
    flag = true;
    }
    
    else if (str.charAt(idx) == '"' && !flag){
    // end index of string
    flag = false;
    end = idx;
char[] mask = new char[end-3-start];
Arrays.fill(mask, 'x');
    string.append(new String(mask)); // need to put 'x' in place
    }
    
    if (!flag){
    string.append(s.charAt(idx));
    }
    
    idx++;
}

复杂度:O(n)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-06
    • 1970-01-01
    • 1970-01-01
    • 2021-06-01
    • 2017-07-03
    • 2020-01-09
    • 2016-06-14
    相关资源
    最近更新 更多