首页 > 解决方案 > 正则表达式找不到匹配项 - .find() 和 .matches() 之间的区别有错吗?

问题描述

代码之前的一些背景知识 - 我维护的系统本质上是一个自动 SFTP 解决方案,它轮询远程服务器,并在它在某个目录中找到与已批准的正则表达式列表匹配的文件时将一些文件拉到我们这边。

昨天,一些新文件开始出现,尽管表格中有一个看似有效的模式,但并没有被匹配为要查看的文件。

这是一个模式的示例,该模式在系统中运行良好,现在仍然可以正常工作,以及我们收到的与之匹配的示例文件(PickUp 是所有文件轮询发生的目录):

/PickUp/(?<foreignid>\\d{9})/rhinoceros\\d{9}\\d{8}.txt

/PickUp/123456789/rhinoceros98765432120201110.txt

这是一个新的没有:

/PickUp/(?<foreignid>\\d{9})_\\d{8}_\\d{10}.zip

/PickUp/123456789_20201110_1234567890.zip

以下是进行匹配的函数部分:

int numMatches = 0;
for (PatternItem item : patternItems)
{
    matcher = item.getPattern().matcher(fileFound);
    if (matcher.find())
    {
        successfulMatch = matcher.group("foreignid");
        numMatches++;
    }
}

if (numMatches == 1)
{
    //download the file in here
}
else if (numMatches > 1)
{
    logger.error("More than one match found for file: " + fileFound + " - regex may be too permissive.");
    return "UNKNOWN_MULTI_MATCH";
}
else
{
    logger.error("Could not find match for file: " + fileFound);
    return "UNKNOWN_NO_MATCH";
}

我已验证该模式确实与文件匹配,并且模式列表中包含正确的模式。我的问题是,错误是否可能是使用matcher.find()而不是的结果matcher.matches()从我matches()对完全匹配的其他答案的阅读来看,似乎find()是部分匹配。事实上,我应该matches()用于我的用例吗?

如果是这样,为什么这还没有打破任何其他模式,所有这些都类似于上面显示的工作模式?这里唯一的区别是,这是第一个 .zip 文件,也是第一次 foreignid 组不代表包含文件本身的子文件夹 - 它只是名称的一部分。

提前感谢您提供的任何帮助/澄清。

标签: javaregex

解决方案


问题都不是。

我修改了您的代码如下(为了让我在我的机器上运行它):

public static void main(String[] args) {
    
    String regex = "/PickUp/(?<foreignid>\\d{9})/rhinoceros\\d{9}\\d{8}.txt";
    String input = "/PickUp/123456789/rhinoceros98765432120201110.txt";
    // String regex = "/PickUp/(?<foreignid>\\d{9})_\\d{8}_\\d{10}.zip";
    // String input = "/PickUp/123456789_20201110_1234567890.zip";
    
    
    Pattern pattern = Pattern.compile(regex);
    Matcher matcher = pattern.matcher(input);
    
    if (matcher.find()) {
        System.out.println(matcher.groupCount());
    } else {
        System.err.println("No match");
    }
}

无论您使用哪一个find()matches(),您的输入将只匹配一组,如 所示groupCount()。您的问题似乎是模式的差异。您/PickUp/(?<foreignid>\\d{9})/rhinoceros\\d{9}\\d{8}.txt匹配的是子目录PickUp而不是文件名。底部模式不使用第一个数字组作为子目录。相反,它使用它作为文件名的一部分;并且只匹配第一组数字。

我不确定这是否是设计使然,但问题在于模式本身;特别是使用“前瞻”(使用括号内的问号)。


推荐阅读