难以逃脱的角色

时间:2010-09-14 17:51:15

标签: java regex escaping character

我需要从字符串中删除一些无效字符并编写StringUtil库的以下代码部分:

public static String removeBlockedCharacters(String data) {
    if (data==null) {
      return data;
    }
    return data.replaceAll("(?i)[<|>|\u003C|\u003E]", "");
}

我有一个测试文件illegalCharacter.txt,其中有一行:

hello \u003c here < and > there

我运行以下单元测试:

@Test
public void testBlockedCharactersRemoval() throws IOException{
    checkEquals(StringUtil.removeBlockedCharacters("a < b > c\u003e\u003E\u003c\u003C"), "a  b  c");
    log.info("Procesing from string directly: " + StringUtil.removeBlockedCharacters("hello \u003c here < and > there"));
    log.info("Procesing from file to string:  " + StringUtil.removeBlockedCharacters(FileUtils.readFileToString(new File("src/test/resources/illegalCharacters.txt"))));
}

我明白了:

INFO - 2010-09-14 13:37:36,111 - TestStringUtil.testBlockedCharactersRemoval(36) | Procesing from string directly: hello  here  and  there
INFO - 2010-09-14 13:37:36,126 - TestStringUtil.testBlockedCharactersRemoval(37) | Procesing from file to string:  hello \u003c here  and  there

我非常困惑:正如您所看到的,代码正确地删除了'&lt;','&gt;'和'\ u003c',如果我传递一个包含这些值的字符串但它无法删除'\ u003c'如果我从包含相同字符串的文件中读取。

我的问题,所以我不再为它丢头发了,是:

  1. 为什么会出现这种行为?
  2. 如何在所有场合更改我的代码以正确剥离\ u003c?
  3. 由于

3 个答案:

答案 0 :(得分:5)

  

hello \ u003c here&lt;和&gt;有

ASCII文件中的\u003c不会这样做,您需要将实际的Unicode字符放在Unicode编码的文本文件中。

答案 1 :(得分:3)

编译源文件时,首先发生的事情是 - 在任何lexing或解析之前 - 是Unicode转义,\u003C\u003E,转换为实际字符, <>。所以你的代码真的是:

return data.replaceAll("(?i)[<|>|<|>]", "");

当您针对字符串文字编译测试代码时,会发生同样的事情;您编写的测试字符串:

"a < b > c\u003e\u003E\u003c\u003C"

......真的是:

"a < b > c>><<"

但是当您从文件中读取测试字符串时,不会发生此类转换;您最终会尝试将六个字符的序列\u003c与单个字符<匹配。如果您确实要匹配\u003C\u003E,那么您的代码应如下所示:

return data.replaceAll("(?i)(?:<|>|\\\\u003C|\\\\u003E)", "");
  • 如果您使用一个反斜杠,Java编译器会将其解释为Unicode转义并将其转换为<>

  • 如果您使用两个反斜杠, regex 编译器会将其解释为Unicode转义符,并认为您要匹配 a { {1}}或<

  • 如果使用三个反斜杠,Java编译器会将其转换为>\<,正则表达式编译器会忽略反斜杠,并尝试匹配{ {1}}或\>

  • 因此,要匹配原始Unicode转义序列,您必须使用四个反斜杠来匹配转义序列中的一个反斜杠。

请注意,我也更改了括号。 <是与>[<|>]<匹配的character class;你想要的是一个alternation

答案 2 :(得分:0)

在我看来,问题不在于您的转义,而在于您正在尝试解析的unicode数据。

您是否尝试使用readFileToString的两个参数版本,将readFileToString(File)来电替换为readFileToString(File, Encoding)

<强>资源