Java 通配符替换

Java WildCard replacement

我有一个文本字段,要求用户输入信息。

JTextField data = new JTextField();

我有一个要求,如果用户输入 *。然后当我搜索数据时,它应该被视为正则表达式通配符。

我正在循环浏览一系列文件并逐行阅读。

for(int i = 0; i < files.length; i++) {
        BufferedReader reader = null;

        try {
            reader = new BufferedReader(new FileReader(files[i]));
            String text = null;

            while ((text = reader.readLine()) != null) {
                if(text.contains(data) return text; // Line that requires wildcard check
            }
        } catch(IOException e) {
            e.printStackTrace();
        } finally{
            try {
                if (reader != null) {
                    reader.close();
                }
            } catch (IOException e) {}
        }
    }

我怎样才能实现这个通配符检查?我要求让'*'成为用户输入后的任何字符。

问题在于搜索字符串可能包含其他在正则表达式中很重要的字符,因此盲目地将 * 转换为 .* 是不安全的。

您需要在搜索字符串的所有部分使用 Pattern.quote,星号除外:

String[] parts = data.split("\*");
Pattern pattern = Pattern.compile(
    Stream.of(parts).map(Pattern::quote).collect(Collectors.joining(".*")));

if (pattern.matcher(text).find()) {
    return text;
}

分解以上语句:

  • data.split("\*") 通过字面匹配 * 字符的正则表达式将字符串拆分为子字符串数组。例子:
    • "ab*cd"{ "ab", "cd" }
    • "1*2345*67"{ "1", "2345", "67" }
  • Stream.of(parts) 从子字符串数组创建一个 Stream
  • map(Pattern:quote) 将 Stream 中的每个元素替换为其引用的等效元素,因此任何正则表达式元字符(* 除外)都将被视为普通字符。因此,原始用户输入中的 "1+1" 实际上会匹配搜索文件中的这三个字符。
  • collect(Collectors.joining(".*")) 将流中的元素重新组合成一个字符串,每个引用部分之间有 .*

附带说明一下,您可以通过将 BufferedReader 放在 try-with-resources statement:

中来避免编写 finally
String[] parts = data.split("\*");
Pattern pattern = Pattern.compile(
    Stream.of(parts).map(Pattern::quote).collect(Collectors.joining(".*")));
Matcher matcher = pattern.matcher("");

for (File file : files) {
    try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
        String text;
        while ((text = reader.readLine()) != null) {
            if (matcher.reset(text).find()) {
                return text;
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

因为 BufferedReader 实现了 AutoCloseable, an implicit finally block will be created which essentially does what you were doing: try to close the BufferedReader while suppressing 关闭尝试可能引起的任何异常。