替换字符串中的非ASCII字符


76

我有一个字符串 A funçãoÃugent在我需要更换字符像çãÃ空字符串。

如何只匹配那些非ASCII字符?

我正在使用一个功能

public static String matchAndReplaceNonEnglishChar(String tmpsrcdta) {
    String newsrcdta = null;
    char array[] = Arrays.stringToCharArray(tmpsrcdta);
    if (array == null)
        return newsrcdta;

    for (int i = 0; i < array.length; i++) {
        int nVal = (int) array[i];
        boolean bISO =
                // Is character ISO control
                Character.isISOControl(array[i]);
        boolean bIgnorable =
                // Is Ignorable identifier
                Character.isIdentifierIgnorable(array[i]);
        // Remove tab and other unwanted characters..
        if (nVal == 9 || bISO || bIgnorable)
            array[i] = ' ';
        else if (nVal > 255)
            array[i] = ' ';
    }
    newsrcdta = Arrays.charArrayToString(array);

    return newsrcdta;
}

但是它不能正常工作..需要什么改进...这里我还有一个问题是,最终的字符串被空格字符代替,从而在字符串中创建了多余的空间。


2
替换成什么??????
dku.rajkumar,2011年

Answers:


154

这将搜索并替换所有非ASCII字母:

String resultString = subjectString.replaceAll("[^\\x00-\\x7F]", "");

感谢您的回复..但是此“ A”仍然无法替换为空字符串。
rahulsri 2011年

3
@rahulsri A是完全有效的ASCII字符。为什么要更换?
FailedDev 2011年

@Dev我认为它不可见,但这是一个拉丁字符,其Unicode值为“ \ u00c3”。
rahulsri 2011年

@rahulsri您可以发布此帖子吗,请通过编辑您的问题将其替换吗?
FailedDev 2011年

41
您很可能也希望剥离不可打印和控制字符。在这种情况下,您可以使用以下正则表达式:"[^\\x20-\\x7E]"或简单地:"[^ -~]"
Zouppen

81

FailedDev的回答很好,但是可以改进。如果要保留ascii等效项,则需要先进行规范化:

String subjectString = "öäü";
subjectString = Normalizer.normalize(subjectString, Normalizer.Form.NFD);
String resultString = subjectString.replaceAll("[^\\x00-\\x7F]", "");

=> will produce "oau"

这样,像“öäü”这样的字符将被映射到“ oau”,这至少保留了一些信息。如果不进行规范化,则结果字符串将为空白。


5
您的回答很好,但是可以改善。在代码中删除正则表达式的用法并将其替换为for循环的速度非常快(20-40倍)。此处更多信息:stackoverflow.com/a/15191508/2511884
Saket 2014年

感谢您的提示。性能差异的程度出乎意料。
MichaelBöckling2014年

2
您可能想使用Normalizer.Form.NFKD而不是NFD-NFKD会将连字之类的内容转换为ascii字符(例如,将fin转换为fi),而NFD不会这样做。
chesterm8 '17

Normalizer.normalize("ãéío – o áá", Normalizer.Form.NFD).replaceAll("[^\\x00-\\x7F]", "");产生“ aeio o aa”,但 echo "ãéío – o áá" | iconv -f utf8 -t ascii//TRANSLIT产生“ aeio-o aa”。有没有一种方法可以让Java像iconv一样用“-”替换“-”?
dvlcube

22

这将是Unicode解决方案

String s = "A função, Ãugent";
String r = s.replaceAll("\\P{InBasic_Latin}", "");

\p{InBasic_Latin}是一个包含以Unicode范围U + 0000..U + 007F的所有字母Unicode的块(参见regular-expression.info

\P{InBasic_Latin} 被否定了 \p{InBasic_Latin}


5
(请注意像我这样困惑的任何人:大写\ P是取反。)
ShreevatsaR 2013年

2
@ user1187719,您可能比“这不起作用”更为精确。这个答案已经收到了一些赞誉,因此不能完全没有用。当然,如果您在Java 7之前拥有Java版本,那么我同意。正则表达式中的Unicode不能在那里工作。
stema 2014年

@stema-我在Java 6中运行了它,因此您的Java 7理论可以发挥作用。

它会删除特殊字符,并用ASCII等效字符“不”替换它们
AL̲̳I

@Ali,是的,您完全理解我的回答。这是五年前的要求。如果不是您所需要的,请与MichaelBöcklings回答。
斯玛

3

您可以尝试这样的事情。字母的特殊字符范围从192开始,因此可以避免在结果中使用此类字符。

String name = "A função";

StringBuilder result = new StringBuilder();
for(char val : name.toCharArray()) {
    if(val < 192) result.append(val);
}
System.out.println("Result "+result.toString());

为什么要检查192而不是128(ASCII表)?您假设使用某种编码(我认为是ISO-8859-1),但是如果编码是ISO-8859-2 / 3/4/5/7 ...怎么办?表格的那些区域中有字母。
stema 2011年

是的,这取决于我们要允许的字符数以及编码。这只是例子。我们可以根据所需的字符和编码添加条件。
mmodi 2011年

1

或者,您可以使用下面的函数从字符串中删除非ASCII字符。您将了解内部工作。

private static String removeNonASCIIChar(String str) {
    StringBuffer buff = new StringBuffer();
    char chars[] = str.toCharArray();

    for (int i = 0; i < chars.length; i++) {
        if (0 < chars[i] && chars[i] < 127) {
            buff.append(chars[i]);
        }
    }
    return buff.toString();
}

0

[更新的解决方案]

可以与“规范化”(规范分解)和“ replaceAll”一起使用,以将其替换为适当的字符。

import java.text.Normalizer;
import java.text.Normalizer.Form;
import java.util.regex.Pattern;

public final class NormalizeUtils {

    public static String normalizeASCII(final String string) {
        final String normalize = Normalizer.normalize(string, Form.NFD);

        return Pattern.compile("\\p{InCombiningDiacriticalMarks}+")
                      .matcher(normalize)
                      .replaceAll("");
    } ...


0

所述ASCII表包含128个代码,总的95个打印字符,其中只有52个字符是字母:

  • [0-127] ASCII码
    • [32-126] 可打印字符
      • [48-57] 数字 [0-9]
      • [65-90] 大写字母 [A-Z]
      • [97-122] 小写字母 [a-z]

您可以使用String.codePoints方法,在获得流int这个字符串的字符和值filter非ASCII字符:

String str1 = "A função, Ãugent";

String str2 = str1.codePoints()
        .filter(ch -> ch < 128)
        .mapToObj(Character::toString)
        .collect(Collectors.joining());

System.out.println(str2); // A funo, ugent

或者,您可以显式指定字符范围。例如,过滤除字母以外的所有内容

String str3 = str1.codePoints()
        .filter(ch -> ch >= 'A' && ch <= 'Z'
                || ch >= 'a' && ch <= 'z')
        .mapToObj(Character::toString)
        .collect(Collectors.joining());

System.out.println(str3); // Afunougent

另请参阅:如何在密码验证中不使用特殊字符(不使用Regex)?

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.