从正则表达式中转义完整路径的一部分,同时保留其中的一部分
Escape a part of the full path from regex while keeping one part of it
需要
我有一个文件夹存档,如下所示:
C:\Users\myUser\myArchive\.
├───v1.ci
│ └───Linux
│ ├───111-001
│ └───222-ci
├───v1.dev
│ └───Linux
│ ├───111-001
│ ├───222-001
│ └───333-001
├───v2.ci
│ └───Linux
│ ├───111-001
│ └───222-ci
├───v2.dev
│ └───Linux
│ ├───111-001
│ ├───222-001
│ └───333-001
└───v2.safe
└───Linux
├───111-001
└───222-ci
我想在 Java 中创建一个静态函数,给定一个存档路径(在本例中为位置 C:\Users\myUser\myArchive\
)和一个模式,returns a List<String>
与匹配该模式的所有文件夹。
例如,如果我说 setupsArchive
= C:\Users\myUser\myArchive\
和 pattern
= v*.ci
,那么列表应该由 v1.ci
和v2.ci
(匹配此模式的两个文件夹)。
注意:不需要递归。我只关心我的存档正下方的文件夹的名称,我不关心它们里面有什么。
代码有效,但仅适用于 Linux
此函数在 运行 Unix 环境下有效:
private static List<String> getVersionsMatchingPattern(String pattern, String setupsArchive) {
File allVersions = new File(setupsArchive);
FileFilter versionFilter = pathname -> pathname.isDirectory() && pathname.toString().matches(setupsArchive + pattern);
File[] filteredVersions = allVersions.listFiles(versionFilter);
List<String> matchedVersions = new ArrayList<>();
for (File version : filteredVersions) {
matchedVersions.add(version.getName());
}
matchedVersions.sort(Collections.reverseOrder());
return matchedVersions;
}
但是,当我 运行 它在 Windows 上时,它会在这一行引发异常:
FileFilter versionFilter = pathname -> pathname.isDirectory() && pathname.toString().matches(setupsArchive + pattern);
异常是 java.util.regex.PatternSyntaxException: Illegal/unsupported escape sequence near index 3
,这是因为(与 Unix 不同)在 Windows 中路径分隔符是反斜杠 \
,当我发送 C:\Users\...
\u
被解释为正则表达式,这在 pathname.toString().matches(setupsArchive + pattern)
部分是非法的。
我试图让它在 Windows
下工作
我明白我需要转义我的正则表达式的 setupsArchive
部分,并只保留 match()
与模式部分。
因此我尝试:
1。将 setupsArchive 放在 Pattern.quote():
周围
FileFilter versionFilter = pathname -> pathname.isDirectory() && pathname.toString().matches(Pattern.quote(setupsArchive) + pattern);
2。仅将正则表达式匹配应用于分析文件夹的基本名称:
FileFilter versionFilter = pathname -> pathname.isDirectory() && pathname.getName().matches(pattern);
在这两种情况下,代码都可以正常编译和执行,但它不会过滤任何内容(即,即使存在与模式匹配的数据,列表仍为空)。
有人知道吗?
您可以利用 Pattern#asPredicate()
作为名称过滤器。
File#getName()
将 return 目录的名称(没有完整路径)。
您可以按类型过滤文件 (dir/file),然后再次过滤结果,或者您可以将文件转换为名称,然后过滤。
final Pattern rx = Pattern.compile("AB"); // Matches names wich contain 'AB'
File baseDir = new File("C:\Users\myUser\myArchive\");
Predicate<String> nameMatcher = rx.asPredicate();
// this will result in a list of File
List<File> result = Arrays.stream(baseDir.listFiles())
.filter(f->f.isDirectory())
.filter(f->nameMatcher.test(f.getName()))
.collect(Collectors.toList());
System.out.println(result); // [C:\Users\myUser\myArchive\ABC003PR, C:\Users\myUser\myArchive\TAB113]
// this will result in a list of String
List<String> result2 = Arrays.stream(baseDir.listFiles())
.filter(f->f.isDirectory())
.map(File::getName)
.filter(nameMatcher)
.collect(Collectors.toList());
System.out.println(result2); // [ABC003PR, TAB113]
需要
我有一个文件夹存档,如下所示:
C:\Users\myUser\myArchive\.
├───v1.ci
│ └───Linux
│ ├───111-001
│ └───222-ci
├───v1.dev
│ └───Linux
│ ├───111-001
│ ├───222-001
│ └───333-001
├───v2.ci
│ └───Linux
│ ├───111-001
│ └───222-ci
├───v2.dev
│ └───Linux
│ ├───111-001
│ ├───222-001
│ └───333-001
└───v2.safe
└───Linux
├───111-001
└───222-ci
我想在 Java 中创建一个静态函数,给定一个存档路径(在本例中为位置 C:\Users\myUser\myArchive\
)和一个模式,returns a List<String>
与匹配该模式的所有文件夹。
例如,如果我说 setupsArchive
= C:\Users\myUser\myArchive\
和 pattern
= v*.ci
,那么列表应该由 v1.ci
和v2.ci
(匹配此模式的两个文件夹)。
注意:不需要递归。我只关心我的存档正下方的文件夹的名称,我不关心它们里面有什么。
代码有效,但仅适用于 Linux
此函数在 运行 Unix 环境下有效:
private static List<String> getVersionsMatchingPattern(String pattern, String setupsArchive) {
File allVersions = new File(setupsArchive);
FileFilter versionFilter = pathname -> pathname.isDirectory() && pathname.toString().matches(setupsArchive + pattern);
File[] filteredVersions = allVersions.listFiles(versionFilter);
List<String> matchedVersions = new ArrayList<>();
for (File version : filteredVersions) {
matchedVersions.add(version.getName());
}
matchedVersions.sort(Collections.reverseOrder());
return matchedVersions;
}
但是,当我 运行 它在 Windows 上时,它会在这一行引发异常:
FileFilter versionFilter = pathname -> pathname.isDirectory() && pathname.toString().matches(setupsArchive + pattern);
异常是 java.util.regex.PatternSyntaxException: Illegal/unsupported escape sequence near index 3
,这是因为(与 Unix 不同)在 Windows 中路径分隔符是反斜杠 \
,当我发送 C:\Users\...
\u
被解释为正则表达式,这在 pathname.toString().matches(setupsArchive + pattern)
部分是非法的。
我试图让它在 Windows
下工作我明白我需要转义我的正则表达式的 setupsArchive
部分,并只保留 match()
与模式部分。
因此我尝试:
1。将 setupsArchive 放在 Pattern.quote():
周围FileFilter versionFilter = pathname -> pathname.isDirectory() && pathname.toString().matches(Pattern.quote(setupsArchive) + pattern);
2。仅将正则表达式匹配应用于分析文件夹的基本名称:
FileFilter versionFilter = pathname -> pathname.isDirectory() && pathname.getName().matches(pattern);
在这两种情况下,代码都可以正常编译和执行,但它不会过滤任何内容(即,即使存在与模式匹配的数据,列表仍为空)。
有人知道吗?
您可以利用 Pattern#asPredicate()
作为名称过滤器。
File#getName()
将 return 目录的名称(没有完整路径)。
您可以按类型过滤文件 (dir/file),然后再次过滤结果,或者您可以将文件转换为名称,然后过滤。
final Pattern rx = Pattern.compile("AB"); // Matches names wich contain 'AB'
File baseDir = new File("C:\Users\myUser\myArchive\");
Predicate<String> nameMatcher = rx.asPredicate();
// this will result in a list of File
List<File> result = Arrays.stream(baseDir.listFiles())
.filter(f->f.isDirectory())
.filter(f->nameMatcher.test(f.getName()))
.collect(Collectors.toList());
System.out.println(result); // [C:\Users\myUser\myArchive\ABC003PR, C:\Users\myUser\myArchive\TAB113]
// this will result in a list of String
List<String> result2 = Arrays.stream(baseDir.listFiles())
.filter(f->f.isDirectory())
.map(File::getName)
.filter(nameMatcher)
.collect(Collectors.toList());
System.out.println(result2); // [ABC003PR, TAB113]