java - 找到随后的数字行(由非字母字符分隔)并计算它们

标签 java regex

我想知道如何使用 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/

相关文章:

java - 如何在 Moshi 中将 PolymorphicJsonAdapterFactory 与接口(interface)一起使用?

javascript - 正则表达式匹配不是由所有相同号码组成的电话号码

java - 比较器和优先级队列

java - 如何使用 Spring Boot 修改 Wildfly/JBoss 配置

java - 如何显示通用 HashMap 条目

java - 访问构造函数中未包含的方法

python - 如果不属于 Python 中的一组匹配模式,则删除字符串中的字符

regex - Lua:模式匹配多字符?重复运算符

regex - 如何替换 lua "in a single pass"中字符串的一部分?

javascript - 在 JavaScript 中查找没有任何数字且至少有一个大写字符的最长子字符串?