我想知道如何使用 java regex 实现以下场景:
- 找出一个字符串中所有不以字母字符分隔的后数,数一数,如果位数在4到5之间(含5),则用
"*"
替换>
例子:
"0000"
将变成"****"
"any text 000 00 more texts"
将变为"any text ***** more texts"
..注意空格已被删除"any text 000 00 more texts 00"
将变为"any text ***** more texts 00"
"any text 000 00 more texts 00 00"
将变为"any text ***** more texts ****"
"any text 00-00 more texts 00_00"
将变为"any text **** more texts ****"
要找到我试过的数字:
(\d*)(?=[^a-bA-Z]*)
和(\d*)([^a-bA-Z])(\d*)
(\d*)([^a-bA-Z])(\d*)
但即使匹配大小写也不起作用。
我需要更多地了解如何进行正则表达式操作。
最佳答案
你可以使用类似的东西:
private static final Pattern p = Pattern
.compile( "(?<!\\d[^a-z\\d]{0,10000})"
+ "\\d([^a-z\\d]*\\d){3}([^a-z\\d]*\\d)?"
+ "(?![^a-z\\d]*\\d)", Pattern.CASE_INSENSITIVE);
public static String replaceSpecial(String text) {
StringBuffer sb = new StringBuffer();
Matcher m = p.matcher(text);
while (m.find()) {
m.appendReplacement(sb, m.group(2) == null ? "****" : "*****");
}
m.appendTail(sb);
return sb.toString();
}
使用演示:
System.out.println(replaceSpecial("foo 123 56 78 bar 12 32 abc 000_00"));
System.out.println(replaceSpecial("0000"));
System.out.println(replaceSpecial("any text 00 00 more texts"));
System.out.println(replaceSpecial("any text 000 00 more texts 00"));
System.out.println(replaceSpecial("any text 000 00 more texts 00 00"));
System.out.println(replaceSpecial("any text 00-00 more texts 00_00"));
结果:
foo 123 56 78 bar **** abc *****
****
any text **** more texts
any text ***** more texts 00
any text ***** more texts ****
any text **** more texts ****
想法/解释:
我们想找到一系列数字,这些数字在零个或多个之间既是非数字又是非字母字符(我们可以用 [^\\da-z]
来表示它们,但 IMO [^a-z\\d]
看起来更好所以我将使用此表格)。这个系列的长度是 4 或 5,我们可以写成
digit([validSeparator]*digit){3,4} //1 digit + (3 OR 4 digits) => 4 OR 5 digits
但我们需要有一些方法来识别我们是否匹配了 4 或 5 个数字,因为我们需要有一些方法来决定我们是否要用 4 或 5 个星号替换这个匹配。
为此,我将尝试将第 5 位数字放在单独的组中,并测试该组是否为空。所以我会尝试创建类似 dddd(d)?
的东西.
这就是我的想法
"\\d([^a-z\\d]*\\d){3}([^a-z\\d]*\\d)?"
// ^^^^^^^^^^^^^^^ possible 5th digit
现在需要确保我们的正则表达式只匹配 dddd(d)
没有被左或右的任何数字包围,因为我们不想匹配任何情况,例如
d ddddd
dddddd
ddddd d
所以我们需要添加测试来检查我们的匹配之前(或之后)是否没有数字(和有效分隔符)。我们可以在这里使用像
这样的负面环视机制"(?<!\\d[^a-z\\d]{0,10000})"
- 我用过{0,10000}
而不是*
因为后视需要有一些最大长度,这会阻止我们*
."(?![^a-z\\d]*\\d)"
所以现在我们需要做的就是组合这些正则表达式(并使其不区分大小写或使用 a-z
代替 a-zA-Z
)
Pattern p = Pattern.compile( "(?<!\\d[^a-z\\d]{0,10000})"
+ "\\d([^a-z\\d]*\\d){3}([^a-z\\d]*\\d)?"
+ "(?![^a-z\\d]*\\d)", Pattern.CASE_INSENSITIVE);
Rest 是 appendTail
的简单用法和 appendReplacement
来自 Matcher 类的方法可以让我们动态决定使用什么来替换已建立的匹配项(我试图在这里更好地解释它:https://stackoverflow.com/a/25081783/1393766)
关于java - 找到随后的数字行(由非字母字符分隔)并计算它们,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35945383/