【问题标题】:A regular expression captures more text than it needs正则表达式捕获的文本比它需要的多
【发布时间】:2021-09-15 10:24:30
【问题描述】:

我想得到整个值 97.47,但正则表达式将其拆分为 9 并通过 7.47 将其添加到不同的字段 这是使用的正则表达式

private static final Pattern COMMISSION_PATTERN =
            Pattern.compile(
                    "(total\\[((?:(?<totalFixed>\\d+)(\\s*(\\+)\\s*)?)?" +
                    "((?<totalPercent>\\d+(\\.\\d{1,2})?)\\s*%)?" +
                    "(\\s*min\\s*(?<totalMin>\\d+))?" +
                    "(\\s*max\\s*(?<totalMax>\\d+))?" +
                    "(\\s*round\\s*(?<totalRound>\\d+))?)?\\])?(\\s*)" +
                    "(partner\\[(?:(\\s*negative:\\s*(?<partnerNegative>(true|false))?\\s*,\\s*)?" +
                    "((?<partnerFixed>\\d+)(\\s*(\\+)\\s*)?)?" +
                    "((?<partnerPercent>\\d+(\\.\\d{1,2})?)\\s*%)?" +
                    "(\\s*min\\s*(?<partnerMin>\\d+))?" +
                    "(\\s*max\\s*(?<partnerMax>\\d+))?" +
                    "(\\s*round\\s*(?<partnerRound>\\d+))?" +
                    "(\\s*mode\\s*(?<partnerMode>\\w+))?)?\\])?");

以下值到达方法中 “总[0]个合作伙伴[97.47%]” 是这样解析的:

String sCommission = "total[0] partner[97.47%]";
for (String comm : sCommission.split("\n")) {
     Matcher matcher = COMMISSION_PATTERN.matcher(comm.trim());
     if (matcher.matches()) {
String sPartnerFixed = matcher.group("partnerFixed");//9
String sPartnerPercent = matcher.group("partnerPercent"); //7.47

它应该是:

String sPartnerFixed = matcher.group("partnerFixed"); //null
String sPartnerPercent = matcher.group("partnerPercent"); //97.47

我不知道正则表达式中的错误在哪里

【问题讨论】:

  • 请尝试生成minimal, reproducible example。这不仅可以帮助我们阅读您的代码,还可以帮助您缩小问题范围。就目前而言,有很多不可读的正则表达式需要解析,甚至可以理解你想要做什么。
  • 对不起,我很笨

标签: java regex


【解决方案1】:

((?&lt;partnerFixed&gt;\d+)(\s*(\+)\s*)?)? 部分中的(\s*(\+)\s*)? 部分是可选的,partnerFixed 组中的\d+ 与正则表达式的(?&lt;partnerPercent&gt;\d+(?:\.\d{1,2})?) 部分“相邻”(可以回溯到)(其中@ 987654327@ 也是必需的,并且匹配一个或多个数字)。因此,除非您告诉正则表达式引擎在这两个数字匹配部分之间明确具有强制性模式,否则您会出现这种行为。

一个可能的解决方案是在(?&lt;partnerFixed&gt;\d+) 部分中\d+ 之后的单词边界,即将"((?&lt;partnerFixed&gt;\\d+)(\\s*(\\+)\\s*)?)?" 替换为"((?&lt;partnerFixed&gt;\\d+\\b)(\\s*(\\+)\\s*)?)?"

解决此问题的更复杂和更精确的方法是使(\s*(\+)\s*)? 模式的某些部分成为强制性的。也就是说,如果有一串数字可选地后跟. 和一个或两个数字,则您不会期望与partnerFixed 匹配。如果有一个partnerFixed 数字,它应该与下一个值分隔什么?我认为应该有一个空格或+ 包含可选的空格,只是从模式中推断出来的。

在后一种情况下,您可以将"((?&lt;partnerFixed&gt;\\d+)(\\s*(\\+)\\s*)?)?" 替换为"((?&lt;partnerFixed&gt;\\d+)(\\s+|\\s*\\+\\s*))?"

this regex demo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多