3

我有一系列链接名称,我试图从中消除特殊字符。从简短的文件浏览来看,我最大的担忧似乎是括号、括号和冒号。: [在与 SELECT和的转义字符搏斗失败后(,我决定排除我想要保留在文件名中的所有内容。

考虑:

String foo = inputFilname ;   //SAMPLE DATA: [Phone]_Michigan_billing_(automatic).html
String scrubbed foo = foo.replaceAll("[^a-zA-Z-._]","") ;

预期结果:Phone_Michigan_billing_automatic.html

当我放弃它时,我的转义字符正则表达式接近 60 个字符。我在更改策略之前保存的最后一个版本是[:.(\\[)|(\\()|(\\))|(\\])]认为我要求的地方escape-character-[()].

毯子排除似乎工作得很好。正则表达式真的那么简单吗?关于这个策略的有效性有什么意见吗?我觉得我错过了一些东西,需要几双眼睛。

4

3 回答 3

1

在我看来,您在这项工作中使用了错误的工具。 StringUtils 有一个名为 replaceChars 的方法,它将用另一个字符替换所有出现的字符。这是文档:

public static String replaceChars(String str,
                              String searchChars,
                              String replaceChars)

Replaces multiple characters in a String in one go. This method can also be used to delete characters.

For example:
replaceChars("hello", "ho", "jy") = jelly.

A null string input returns null. An empty ("") string input returns an empty string. A null or empty set of search characters returns the input string.

The length of the search characters should normally equal the length of the replace characters. If the search characters is longer, then the extra search characters are deleted. If the search characters is shorter, then the extra replace characters are ignored.

 StringUtils.replaceChars(null, *, *)           = null
 StringUtils.replaceChars("", *, *)             = ""
 StringUtils.replaceChars("abc", null, *)       = "abc"
 StringUtils.replaceChars("abc", "", *)         = "abc"
 StringUtils.replaceChars("abc", "b", null)     = "ac"
 StringUtils.replaceChars("abc", "b", "")       = "ac"
 StringUtils.replaceChars("abcba", "bc", "yz")  = "ayzya"
 StringUtils.replaceChars("abcba", "bc", "y")   = "ayya"
 StringUtils.replaceChars("abcba", "bc", "yzx") = "ayzya"

所以在你的例子中:

    String translated = StringUtils.replaceChars("[Phone]_Michigan_billing_(automatic).html", "[]():", null);
    System.out.println(translated);

将输出:

Phone_Michigan_billing_automatic.html

这将比您可以编写的任何正则表达式更直接和更容易理解。

于 2013-02-01T16:53:51.403 回答
1

我认为您的正则表达式可以简单到\W匹配所有不是单词字符(字母、数字和下划线)的内容。这是否定的\w

所以你的代码变成:

foo.replaceAll("\W","");

正如评论中指出的那样,上面还删除了句点,这也将有助于保留句点:

foo.replaceAll("[^\w.]","");

细节:转义所有不是的东西(^字符类内部)、数字、下划线、字母( the \w)或点( the \.

如上所述,您可能希望将其他字符列入白名单:例如-. 只需将它们包含在您的角色类中即可。

foo.replaceAll("[^\w.\-]","");
于 2013-02-01T17:44:01.760 回答
1

我认为你的正则表达式是要走的路。一般来说,白名单值而不是黑名单几乎总是更好。(只允许你知道好的字符而不是消除你认为不好的所有字符)从安全的角度来看,这个正则表达式应该是首选。你永远不会得到一个包含无效字符的 inputFilename 。

suggested regex: [^a-zA-Z-._]
于 2013-02-01T19:51:06.800 回答