【问题标题】:Hard time with escape character逃脱角色的艰难时期
【发布时间】:2010-09-14 17:51:14
【问题描述】:

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

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

我有一个包含一行的测试文件非法字符.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

我很困惑:如您所见,如果我传递一个包含这些值的字符串,代码会正确删除 '' 和 '\u003c',但它无法删除 '\u003c'如果我从包含相同字符串的文件中读取。

我的问题是:

  1. 为什么会出现这种行为?
  2. 如何更改我的代码以在所有情况下正确剥离 \u003c?

谢谢

【问题讨论】:

    标签: java regex escaping character


    【解决方案1】:

    你好\u003c这里那里

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

    【讨论】:

      【解决方案2】:

      当你编译你的源文件时,首先发生的事情——在任何词法分析或解析之前——是 Unicode 转义,\u003C\u003E,被转换为实际字符,&lt;&gt;。所以你的代码真的是:

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

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

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

      ……真的是:

      "a < b > c>><<"
      

      但是当您从文件中读取测试字符串时,不会发生这种转换;您最终会尝试将六个字符序列\u003c 与单个字符&lt; 匹配。如果你真的想匹配\u003C\u003E,你的代码应该是这样的:

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

      • 如果您使用 两个 反斜杠,regex 编译器会将其解释为 Unicode 转义,并认为您想要 匹配 @ 987654337@或&gt;

      • 如果使用三个反斜杠,Java 编译器会将其转换为\&lt;\&gt;,正则表达式编译器会忽略反斜杠,并尝试匹配&lt; 或@ 987654342@.

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

      请注意,我也更改了您的括号。 [&lt;|&gt;] 是匹配 &lt;|&gt;character class;你想要的是alternation

      【讨论】:

      • 谢谢大家:解释,发现我关于括号的错误,并提供我正在寻找的修复。
      【解决方案3】:

      在我看来,问题不在于您的转义,而在于您拥有要解析的 unicode 数据这一事实。

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

      资源

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-11
        • 2014-06-30
        • 1970-01-01
        • 2013-03-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多