【问题标题】:Java Pattern/ MatcherJava 模式/匹配器
【发布时间】:2014-11-05 21:54:33
【问题描述】:

这是一个示例文本:\1f\1e\1d\020028。我无法修改输入文本,我正在从文件中读取一长串文本。


我想提取以下内容:\1f\1e\1d\02

为此,我编写了以下正则表达式模式:"\\[a-fA-F0-9]"

我正在使用PatternMatcher 类,但我的匹配器无法使用上述正则表达式找到模式。我已经用一些在线正则表达式网站上的文本测试了这个正则表达式,令人惊讶的是它在那里工作。

我哪里出错了?

原文代码:

public static void main(String[] args) {
    String inputText = "\1f\1e\1d\02002868BF03030000000000000000S023\1f\1e\1d\03\0d";
    inputText        = inputText.replace("\\", "\\\\");

    String regex     = "\\\\[a-fA-F0-9]{2}";

    Pattern p = Pattern.compile(regex);
    Matcher m = p.matcher(inputText);

    while (m.find()) {
        System.out.println(m.group());
    }
}

输出:没有打印出来

【问题讨论】:

  • 我猜你的一些反斜杠正在逃避你不想要的东西。不过,您必须向我们展示您的实际代码才能确定。
  • \\[a-fA-F0-9] 查找后跟一个字母或数字的反斜杠。我认为您想查找后跟两个字母或数字的反斜杠。我怀疑你可以弄清楚如何解决这个问题。
  • 您是否正确格式化输入字符串?我认为应该是 '\\1f\\1e\\1d\\020028'。
  • 为了帮助您更轻松地发布有关如何使用此正则表达式的代码示例。
  • 这是您输入文件中的文本吗?我们可以看看你是怎么读的吗?另外,当您打印红色时您会看到什么?

标签: java regex pattern-matching


【解决方案1】:

(在 OP 添加更多详细信息后答案已更改)

你的字符串

String inputText = "\1f\1e\1d\02002868BF03030000000000000000S023\1f\1e\1d\03\0d";

实际上不包含任何\ 文字,因为根据3.10.6. Escape Sequences for Character and String Literals 部分中的Java 语言规范,\xxx 将被解释为在Unicode 表中索引的字符,octal (base/radix 8) 值由xxx 部分表示。

示例\123 = 1*82 + 2*81 + 3 *80 = 1*64 + 2*8 + 3*1 = 64+16+3 = 83 代表character S

如果您在问题中提出的字符串与您的文本文件中的字符串完全相同,那么您应该将其写为

String inputText = "\\1f\\1e\\1d\\02002868BF03030000000000000000S023\\1f\\1e\\1d\\03\\0d";

(使用转义的 \ 现在将代表文字)。


(我的答案的旧版本)

如果不查看您的代码,很难判断您到底做错了什么。您至少应该能够找到\1\1\1\0,因为您的正则表达式可以匹配一个\ 和一个放置在其后的十六进制字符。

无论如何,您可以通过以下方式找到您提到的结果:

String text = "\\1f\\1e\\1d\\020028";
Pattern p = Pattern.compile("\\\\[a-fA-F0-9]{2}");
//                                          ^^^--we want to find two hexadecimal 
//                                               characters after \
Matcher m = p.matcher(text);
while (m.find())
    System.out.println(m.group());

输出:

\1f
\1e
\1d
\02

【讨论】:

  • 您提到的代码有效。但是,当我做了与您在上面看到的类似的事情时,它不起作用。
【解决方案2】:

您需要正确读取文件并将“\”字符替换为“\\”。假设你的项目中有一个名为 test_file 的文件,内容如下:

\1f\1e\1d\02002868BF03030000000000000000S023\1f\1e\1d\03\0d

这是读取文件并提取值的代码:

public static void main(String[] args) throws IOException, URISyntaxException {        
    Test t = new Test();
    t.test();
}

public void test() throws IOException {        
    BufferedReader br =
        new BufferedReader(
            new InputStreamReader(
                getClass().getResourceAsStream("/test_file.txt"), "UTF-8"));
    String inputText;

    while ((inputText = br.readLine()) != null) {
        inputText = inputText.replace("\\", "\\\\");

        Pattern pattern = Pattern.compile("\\\\[a-fA-F0-9]{2}");
        Matcher match = pattern.matcher(inputText);

        while (match.find()) {
            System.out.println(match.group());
        }
    }
}

【讨论】:

  • 您的代码确实有效。但是,当我做了与您在上面看到的类似的事情时,它不起作用。
  • 问题是转义输入字符串。检查更新。我使用了来自 apache commons lang 的 StringEscapeUtils。
  • @bullzeye 解释 escapeJava 将返回 Unicode 表示而不是八进制表示,因此您将得到 \1\0 而不是 \u0001\u0000 这就是为什么 replace("\\u000", "\\") 是需要(将\u0001 转换为\1 就像在您的字符串中一样)。
  • @bullzeye 无论如何,这种方法会失败,例如在\03 的情况下,因为它假设您将只有\x 用于八进制值,而不是\xx 可能代表更大值的值超过 15 需要使用两个十六进制字符编写,这将使其转义返回 \u00XX
  • @bullzeye 此方法也不会转义由\123(十进制83 -> 'S' 字符)表示的字符,因为它是Java语言中使用的普通字符,不需要转义.
【解决方案3】:

尝试添加一个 .最后,比如:

\\[a-fA-F0-9].

【讨论】:

    【解决方案4】:

    如果你不想修改输入字符串,你可以试试这样的:

    static public void main(String[] argv) {
    
                String s = "\1f\1e\1d\020028";
                Pattern regex = Pattern.compile("[\\x00-\\x1f][0-9A-Fa-f]");
                Matcher match = regex.matcher(s);
                while (match.find()) {
                        char[] c = match.group().toCharArray();
                        System.out.println(String.format("\\%d%s",c[0]+0, c[1])) ;
                }
        }
    

    是的,它并不完美,但你明白了。

    【讨论】:

    • 谢谢!该解决方案部分有效。对于我在修改后的答案中提到的输入字符串,以下是输出:'\1f \1e \1d \160 \1f \1e \1d \0d'
    猜你喜欢
    • 2015-04-28
    • 2015-01-10
    • 1970-01-01
    • 2012-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多