【问题标题】:Split string using multiple patterns, where second pattern matches smaller parts of the first使用多个模式拆分字符串,其中第二个模式匹配第一个模式的较小部分
【发布时间】:2020-08-10 15:10:12
【问题描述】:

我正在读取字符串中的特殊“格式代码”并尝试拆分字符串,以便将这些格式代码和字符串的文本分开。

格式代码有两种“类型”:“编码”十六进制颜色:§x§7§3§7§5§f§f 和其他格式为§r 的代码。

给定示例字符串:§x§7§3§7§5§f§f§ltest1 §rtest2

我需要将较大的模式拆分为一个整体,然后再拆分较小的模式。我可以分别对这些模式做我想做的事,但是在将它们组合成一个正则表达式时遇到了麻烦。因为第二个模式匹配第一个模式的片段,所以它只是将所有内容分成更小的组。

我正在尝试这个:

for (String substr : "§x§7§3§7§5§f§f§ltest1 §rtest2".split("((?<=(§x(§[0-9a-f]){6}))|(?<=§[0-9a-z])|(?=§[0-9a-z]))")) {
  System.out.println(substr);
}

我的预期输出是:

§x§7§3§7§5§f§f
§l
test1
§r
test

我的实际输出是:

§x
§7
§3
§7
§5
§f
§f
§l
test1
§r
test2

当我将表达式拆分为不同的 split 测试时,它们可以工作,只是不能一起工作

【问题讨论】:

    标签: java regex


    【解决方案1】:

    您可以使用这个简化的正则表达式进行匹配,而不是拆分:

    §x(?:§[0-9a-f]){6}|§[0-9a-z]|[^§\s]+
    

    RegEx Demo

    正则表达式详细信息:

    • §x(?:§[0-9a-f]){6}:匹配以 §x 开头的文本和 6 个十六进制字符
    • |:或者
    • §[0-9a-z]:匹配以§ 和字母数字开头的文本
    • |:或者
    • [^§\s]+:匹配 1+ 个非空白和非§ 字符

    代码:

    final String regex = "§x(?:§[0-9a-f]){6}|§[0-9a-z]|[^§\\s]+";
    final String string = "§x§7§3§7§5§f§f§ltest1 §rtest2";
    
    final Pattern pattern = Pattern.compile(regex);
    final Matcher matcher = pattern.matcher(string);
    
    while (matcher.find()) {
        System.out.println( matcher.group(0) );
    }
    

    【讨论】:

    • 这看起来很完美。这对split 有什么性能优势吗?性能在这里不是一个大问题,它不会经常运行,但值得关注。
    • 这样会更有效率。肯定没有环顾四周
    • 我注意到,如果 §r 被移动,它就不再分离,但我不确定为什么,因为正则表达式在 regex101 测试中仍然匹配它。 §x§7§3§7§5§f§f§ltest1§r test2
    • 看起来 §x(?:§[0-9a-f]){6}|§[0-9a-z]|[^§]+ 有效,但也需要调整以忽略空格。
    • 是的,这确实是个好主意。我刚刚用[^§\s]+ 选项更新了答案。
    【解决方案2】:

    您可以使用以下正则表达式:

    See it working here

     ?((?:§[^§])(?=[^§])|[^§ ]{2,})
    

    它是如何工作的:

    • ? 可选匹配空格字符
    • ((?:§[^§])(?=[^§])|[^§ ]{2,}) 捕获以下任一:
      • (?:§[^§])(?=[^§]) 匹配以下内容:
        • (?:§[^§]) 匹配 § 后跟除 § 之外的任何字符
        • (?=[^§]) 前瞻确保后面的内容不是 §(与 (?!§) 相同,但更高效)
      • [^§ ]{2,} 匹配除§ 或空格两次或多次以外的任何字符

    替换为\n$1

    结果:

    §x§7§3§7§5§f§f
    §l
    test1
    §r
    test2
    

    【讨论】:

    • 这个可以改成split吗?我实际上并不是在每个段之间寻找新行,我需要在每个组件上运行逻辑(主要将格式代码转换为可用的东西),所以我需要能够按照“输出”暗示的顺序迭代它们。
    • @helion3 您应该将第二个字符串示例添加到您的问题中并添加预期结果。
    猜你喜欢
    • 2015-08-08
    • 2011-06-28
    • 1970-01-01
    • 2020-08-04
    • 1970-01-01
    • 2015-01-22
    • 1970-01-01
    • 2020-02-09
    • 1970-01-01
    相关资源
    最近更新 更多