如何在Glob模式中对中间位置的字符进行取反?
Java NIO Glob模式:如何实现中间位置字符取反
嘿,这个问题我之前也碰到过,Java NIO的Glob语法确实在处理“排除中间某个字符”的时候有点绕,咱们一步步理清楚:
首先得搞明白为什么你用*[!.]*达不到预期效果——这个模式的逻辑是“任意数量的任意字符 + 一个非点字符 + 任意数量的任意字符”。它只是要求字符串里至少存在一个非点字符,完全不关心有没有点。比如"a.b"这种中间带点的文件名,会被匹配上:要么前面的*匹配"a",[!.]匹配"b",后面的*匹配空;要么前面的*匹配空,[!.]匹配"a",后面的*匹配".b"。所以它根本过滤不掉中间带点的文件。
那该怎么实现不同场景下的中间字符取反呢?分两种情况说:
场景1:匹配整个路径段中完全不包含某个字符(比如文件名不含任何点)
Java Glob本身没有直接支持“整个字符串不包含某字符”的语法,这时候咱们可以用反向匹配的思路:先写一个能匹配“包含目标字符”的Glob模式,然后过滤掉符合这个模式的结果。
比如要找出当前目录下所有文件名不含点的文件,代码可以这么写:
import java.nio.file.*; import java.io.IOException; public class GlobExample { public static void main(String[] args) { Path dir = Paths.get("."); // 先定义匹配"含有点的文件名"的Glob模式 PathMatcher hasDotMatcher = FileSystems.getDefault().getPathMatcher("glob:*.*"); try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir, path -> { // 过滤掉匹配"含有点"的文件,剩下的就是不含点的 return !hasDotMatcher.matches(path.getFileName()); })) { for (Path entry : stream) { System.out.println("匹配到的文件:" + entry.getFileName()); } } catch (IOException e) { e.printStackTrace(); } } }
场景2:匹配某个特定位置的字符不是目标字符
如果你的需求是“第N个字符不能是某个字符”,那可以用?(匹配单个任意字符)结合[!x]来定位位置。比如:
- 第二个字符不能是'a':用模式
?[!a]*(?匹配第一个任意字符,[!a]确保第二个不是a,*匹配剩下的所有字符) - 第三个字符不能是'b':用模式
??[!b]*
这种方式只针对固定位置的字符取反,适合明确位置的场景。
总的来说,Java Glob更擅长正向匹配,遇到“排除类”的需求时,反向过滤往往是更靠谱的方案。
内容的提问来源于stack exchange,提问作者user3501758
相关产品推荐
相关产品推荐

