是否有正则表达式方法用另一组替换一组字符(如shell tr​​命令)?

Liu*_* 刘研 8 java regex replace

shell tr命令支持用另一组替换一组字符.例如,echo hello | tr [a-z] [A-Z]将转换helloHELLO.

但是,在java中,我必须单独替换每个字符,如下所示

"10 Dogs Are Racing"
    .replaceAll ("0", "?")
    .replaceAll ("1", "?")
    .replaceAll ("2", "?")
    // ...
    .replaceAll ("9", "?")
    .replaceAll ("A", "?")
    // ...
;
Run Code Online (Sandbox Code Playgroud)

Apache的公地郎库提供了一个方便replaceChars的方法做这样的替换.

// half-width to full-width
System.out.println
(
    org.apache.commons.lang.StringUtils.replaceChars
    (
        "10 Dogs Are Racing",
        "0123456789ABCDEFEGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
        "???????????????????????????????????????????????????????????????"
    )
);
// Result:
// ?? ???? ??? ??????
Run Code Online (Sandbox Code Playgroud)

但正如你所看到的,在某个时候searchChars/replaceChars太长(也太无聊了,请,如果你想找到它复制的字符),并且可以通过一个简单的正则表达式来表示[0-9A-Za-z]/ [?-??-??-?].是否有正则表达方式来实现这一目标?

Dam*_*ell 5

没有.

(一些额外的字符,以便SO允许我发布我的简洁答案)


bee*_*jay 5

虽然没有直接的方法可以做到这一点,但构建自己的实用程序函数以便与之结合使用replaceChars相对简单.下面的版本接受简单的字符类,没有[]; 它不做类否定([^a-z]).

对于您的用例,您可以:

StringUtils.replaceChars(str, charRange("0-9A-Za-z"), charRange("?-??-??-?"))
Run Code Online (Sandbox Code Playgroud)

码:

public static String charRange(String str) {
    StringBuilder ret = new StringBuilder();
    char ch;
    for(int index = 0; index < str.length(); index++) {
        ch = str.charAt(index);
        if(ch == '\\') {
            if(index + 1 >= str.length()) {
                throw new PatternSyntaxException(
                    "Malformed escape sequence.", str, index
                );
            }
            // special case for escape character, consume next char:
            index++;
            ch = str.charAt(index);
        }
        if(index + 1 >= str.length() || str.charAt(index + 1) != '-') {
            // this was a single char, or the last char in the string
            ret.append(ch);
        } else {
            if(index + 2 >= str.length()) {
                throw new PatternSyntaxException(
                    "Malformed character range.", str, index + 1
                );
            }
            // this char was the beginning of a range
            for(char r = ch; r <= str.charAt(index + 2); r++) {
                ret.append(r);
            }
            index = index + 2;
        }
    }
    return ret.toString();
}
Run Code Online (Sandbox Code Playgroud)

生产:

0-9A-Za-z : 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
?-??-??-? : ??????????????????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)