Java Regex和PathMatcher

时间:2016-10-31 23:02:48

标签: java regex matcher

我正在用Java编写一个应用程序,它显示文件列表,其中文件名中的第一个单词与用户定义的字符串匹配,然后根据某些首选项删除或重新排列它们。我目前正处于找到找到我的文件的好方法的阶段。使用this Java Tutorial我得到了类似的结果:

Path source = Paths.get(sourceText.getText());
Path dest = Paths.get(destText.getText());

System.out.println("Source:" + source.toString());
System.out.println("P/N: " + partNoText.getText());

String matchString = "glob:**" + partNoText.getText() + "*";

System.out.println("Matching: " + matchString);

fileFinder = new FileFinder(matchString);

try {
    Files.walkFileTree(source, fileFinder);
} catch (IOException e1) {
    e1.printStackTrace();
}
for (Path path : fileFinder.getResult()) {
    System.out.println("Moving: " + path.getFileName());
    Path target = Paths.get(dest.toString() + "\\" + path.getFileName());

    try {
        Files.move(path, target, REPLACE_EXISTING);
    } catch (IOException e1) {
        e1.printStackTrace();
    }
}

其中FileFinder扩展SimpleFileVisitor并具有此visitFile方法:

public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
    System.out.println(file.toString());
    System.out.println(fileMatcher.matches(file));
    if (fileMatcher.matches(file)) {
        result.add(file);
        return FileVisitResult.CONTINUE;
    }
    return FileVisitResult.CONTINUE;
}

我的问题是,glob会选择文件名中包含零件号的文件。以任何方式。因此,如果我的文件被称为“12345 RevA Really Big Part 2:Electric Bugaloo”,那么如果用户输入“1”或“123”或“Bugaloo”,则该字符串将匹配。理想情况下,只有在用户输入“12345”时才会匹配。

我尝试将我的matchString切换为"regex: .*" + partNoText + "\\b",这适用于我从this other Java Tutorial修改的正则表达式测试工具。我究竟做错了什么? PathMatcher的工作方式与常规Matcher的工作方式不同吗?

P.S。其中包含“Text”一词的任何变量,如sourceTextpartNoText都是JTextFields。 Hopefull是代码的唯一部分,从我剪掉它的内容中大部分都不清楚。

2 个答案:

答案 0 :(得分:1)

" PathMatcher的工作方式与常规匹配器不同吗?"
是。 PathMatcher使用文件名 globbing [1] ,而Matcher使用正则表达式

请参阅您链接的教程中的What Is a Glob?,并将其与java.util.regex.Pattern的文档进行比较 Globbing与正则表达式匹配相当有限。

如果你有一个严格遵守的严格文件命名约定,你可能会使用globbing(我收回我之前评论的最后一部分)。

我们说你的文件被命名为
numeric part number - space - optional revision & space - description

也就是说,零件号可以有可变数位,但零件号后面的空格是必需的并且始终存在。

所以你的例子" 12345 RevA Really Big Part 2:Electric Bugaloo" 适合与partNum == 12345,revision =" RevA",description ="真的很重要的第2部分:电动Bugaloo"

用户输入部件号P/N: 123作为变量userPN,并将glob构造为
String glob = userPN + " *";导致全局等于"123 *"
这将匹配12345,如你所愿,因为3之后的空格将与4不匹配。

如果文件名中的部件号后面有所需的空格,但接下来是总是字母,无论是修订版还是描述版,都可以构建一个glob作为
String glob = userPN + "[A-Z,a-z]*";给出glob = 123[A-Z,a-z]*,它也不匹配12345,因为字母必须跟随123而且4不在该字符范围内。

你可以让你的角色范围更复杂,对于可选空间说[A-Z,a-z, ],这取决于你的需要,这一切都归结为你的文件命名约定。您需要非常准确地陈述该惯例并遵守它。

[1]如果您指定"语法" PathMatcher 可以使用正则表达式而不是通配符调用FileSystem.getPathMatcher(String)时为regex。这就像是

FileSystem fs = FileSystems.getDefault();
PathMatcher pm = fs.getPathMatcher("regex:\\d{5}\\s.*");

答案 1 :(得分:0)

我认为你继续这么复杂的方式。当你不去寻找事件时,为什么你会首先使用拍拍Marc她。

通过文件树和每个目录迭代目录流来匹配你的glob会容易得多。