【问题标题】:How can you strip non-ASCII characters from a string? (in C#)如何从字符串中去除非 ASCII 字符? (在 C# 中)
【发布时间】:2010-09-12 12:10:21
【问题描述】:

如何从字符串中去除非 ASCII 字符? (在 C# 中)

【问题讨论】:

  • 根据 sinelaw 的回答 below,如果您想替换非 ASCII 字符,请参阅 this answer

标签: c# ascii


【解决方案1】:
string s = "søme string";
s = Regex.Replace(s, @"[^\u0000-\u007F]+", string.Empty);

【讨论】:

  • 对于我们这些受到 RegEx 挑战的人,您介意用简单的英语写出您的 RegEx 模式吗?换句话说,“^ 做这个”等等......
  • @Metro Smurf ^ 是非运算符。它告诉正则表达式查找不匹配的所有内容,而不是匹配的所有内容。 \u####-\u#### 表示匹配的字符。\u0000-\u007F 是 utf-8 或 unicode 中的前 255 个字符的等价物,它们始终是 ascii 字符。因此,您匹配每个非 ascii 字符(因为不是)并对匹配的所有内容进行替换。
  • 可打印字符的范围是 0020-007E,供寻找正则表达式替换不可打印字符的人使用
  • @GordonTucker \u0000-\u007F 等同于 utf-8 或 unicode 中的 前 127 个字符,而不是前 225。请参阅 table
  • @full_prog_full 这就是为什么我在一分钟后回复自己,纠正自己说是 127 而不是 255。:)
【解决方案2】:

这是一个不使用正则表达式的纯 .NET 解决方案:

string inputString = "Räksmörgås";
string asAscii = Encoding.ASCII.GetString(
    Encoding.Convert(
        Encoding.UTF8,
        Encoding.GetEncoding(
            Encoding.ASCII.EncodingName,
            new EncoderReplacementFallback(string.Empty),
            new DecoderExceptionFallback()
            ),
        Encoding.UTF8.GetBytes(inputString)
    )
);

它可能看起来很麻烦,但它应该是直观的。它使用 .NET ASCII 编码来转换字符串。在转换过程中使用 UTF8,因为它可以表示任何原始字符。它使用 EncoderReplacementFallback 将任何非 ASCII 字符转换为空字符串。

【讨论】:

  • 完美!在将字符串保存到 RTF 文档之前,我使用它来清理字符串。非常感谢。比 Regex 版本更容易理解。
  • 你真的觉得它更容易理解吗?对我来说,所有不相关的东西(回退、转换为字节等)都在将注意力从实际发生的事情上转移开。
  • @Brandon,实际上,这种技术并不比其他技术做得更好。所以类比是使用普通的老式螺丝刀而不是花哨的 iScrewDriver Deluxe 2000。:)
  • @bzim 这就像在螺丝上使用锤子:) 好的,不。这就像使用汽车发动机的曲轴来驱动螺丝一样。我们开始了。
  • 一个优点是我可以轻松地将 ASCII 替换为 ISO 8859-1 或其他编码:)
【解决方案3】:

philcruz's Regular Expression solution的启发,我做了一个纯LINQ解决方案

public static string PureAscii(this string source, char nil = ' ')
{
    var min = '\u0000';
    var max = '\u007F';
    return source.Select(c => c < min ? nil : c > max ? nil : c).ToText();
}

public static string ToText(this IEnumerable<char> source)
{
    var buffer = new StringBuilder();
    foreach (var c in source)
        buffer.Append(c);
    return buffer.ToString();
}

这是未经测试的代码。

【讨论】:

  • 对于那些没有抓住它的人来说,这是一个基于 C# 4.0 LINQ 的解决方案。 :)
  • 代替单独的 ToText() 方法,如何将 PureAscii() 的第 3 行替换为: return new string(source.Select(c => c max ? nil : c).ToArray());
  • 或者 ToText 为:return (new string(source)).ToArray() - 取决于什么表现最好。将 ToText 作为扩展方法仍然很好 - 流利/管道样式。 :-)
  • 该代码将非 ASCII 字符替换为空格。要删除它们,请将 Select 更改为 Where:return new string( source.Where( c =&gt; c &gt;= min &amp;&amp; c &lt;= max ).ToArray() );
  • @Foozinator 该代码允许您指定用哪个字符替换非 ASCII 字符。默认情况下它使用一个空格,但如果它被称为 .PureASCII(Char.MinValue),它会将所有非 ASCII 替换为 '\0' - 这仍然不是完全剥离它们,但结果相似。
【解决方案4】:

如果您不想剥离,而是要将带有重音的拉丁字符实际转换为非重音字符,请查看以下问题:How do I translate 8bit characters into 7bit characters? (i.e. Ü to U)

【讨论】:

  • 我什至没有意识到这是可能的,但这对我来说是一个更好的解决方案。我将将此链接添加到对该问题的评论中,以便其他人更容易找到。谢谢!
【解决方案5】:

我使用了这个正则表达式:

    string s = "søme string";
    Regex regex = new Regex(@"[^a-zA-Z0-9\s]", (RegexOptions)0);
    return regex.Replace(s, "");

【讨论】:

  • 这也会删除标点符号,以防万一这不是某人想要的。
【解决方案6】:

我发现以下稍微更改的范围对于从数据库中解析注释块很有用,这意味着您不必与制表符和转义符抗衡,因为这会导致 CSV 字段变得混乱。

parsememo = Regex.Replace(parsememo, @"[^\u001F-\u007F]", string.Empty);

如果要避免其他特殊字符或特定标点符号检查the ascii table

【讨论】:

  • 如果有人没有注意到其他 cmets,可打印的字符实际上是 @"[^\u0020-\u007E]"。如果您好奇,可以通过以下链接查看表格:asciitable.com
【解决方案7】:

不需要正则表达式。只需使用编码...

sOutput = System.Text.Encoding.ASCII.GetString(System.Text.Encoding.ASCII.GetBytes(sInput));

【讨论】:

  • 这不起作用。这不会去除 unicode 字符,而是将它们替换为 ?字符。
  • @David 是对的。至少我在尝试时得到了????nacho??たまねこnachoなち in mono 3.4
  • 您可以实例化自己的 Encoding 类,而不是替换字符,而是删除它们。见GetEncoding方法:msdn.microsoft.com/en-us/library/89856k4b(v=vs.110).aspx
【解决方案8】:

我相信 MonsCamus 的意思是:

parsememo = Regex.Replace(parsememo, @"[^\u0020-\u007E]", string.Empty);

【讨论】:

  • 恕我直言,这个答案比公认的答案更好,因为它去掉了控制字符。
【解决方案9】:

这不是最佳的性能,而是一种非常直接的 Linq 方法:

string strippedString = new string(
    yourString.Where(c => c <= sbyte.MaxValue).ToArray()
    );

缺点是所有“幸存的”字符首先放入char[] 类型的数组中,然后在string 构造函数不再使用它之后将其丢弃。

【讨论】:

    【解决方案10】:

    我来这里寻找扩展 ascii 字符的解决方案,但找不到。我找到的最接近的是bzlm's solution。但这仅适用于最高 127 的 ASCII 代码(显然您可以替换他代码中的编码类型,但我认为理解起来有点复杂。因此,分享这个版本)。这是适用于extended ASCII codes i.e. upto 255 的解决方案,即ISO 8859-1

    它发现并去除非ascii字符(大于255)

    Dim str1 as String= "â, ??î or ôu?� n☁i✑?++$-?♓!???‼⁉4⃣od;/⏬'®;?☕?:☝)??///?1!@#"
    
    Dim extendedAscii As Encoding = Encoding.GetEncoding("ISO-8859-1", 
                                                    New EncoderReplacementFallback(String.empty),
                                                    New DecoderReplacementFallback())
    
    Dim extendedAsciiBytes() As Byte = extendedAscii.GetBytes(str1)
    
    Dim str2 As String = extendedAscii.GetString(extendedAsciiBytes)
    
    console.WriteLine(str2)
    'Output : â, ??î or ôu ni++$-!‼⁉4od;/';:)///1!@#$%^yz:
    

    这是working fiddle for the code

    按要求替换编码,其余保持不变。

    【讨论】:

    • 唯一一个仅从该字符串“Ω c çã”中删除Ω的方法。非常感谢!
    【解决方案11】:

    我使用这个正则表达式过滤掉文件名中的坏字符。

    Regex.Replace(directory, "[^a-zA-Z0-9\\:_\- ]", "")
    

    这应该是文件名允许的所有字符。

    【讨论】:

    【解决方案12】:

    亡灵术。
    此外,bzlm 的方法可用于删除不在任意字符集中的字符,而不仅仅是 ASCII:

    // https://en.wikipedia.org/wiki/Code_page#EBCDIC-based_code_pages
    // https://en.wikipedia.org/wiki/Windows_code_page#East_Asian_multi-byte_code_pages
    // https://en.wikipedia.org/wiki/Chinese_character_encoding
    System.Text.Encoding encRemoveAllBut = System.Text.Encoding.ASCII;
    encRemoveAllBut = System.Text.Encoding.GetEncoding(System.Globalization.CultureInfo.InstalledUICulture.TextInfo.ANSICodePage); // System-encoding
    encRemoveAllBut = System.Text.Encoding.GetEncoding(1252); // Western European (iso-8859-1)
    encRemoveAllBut = System.Text.Encoding.GetEncoding(1251); // Windows-1251/KOI8-R
    encRemoveAllBut = System.Text.Encoding.GetEncoding("ISO-8859-5"); // used by less than 0.1% of websites
    encRemoveAllBut = System.Text.Encoding.GetEncoding(37); // IBM EBCDIC US-Canada
    encRemoveAllBut = System.Text.Encoding.GetEncoding(500); // IBM EBCDIC Latin 1
    encRemoveAllBut = System.Text.Encoding.GetEncoding(936); // Chinese Simplified
    encRemoveAllBut = System.Text.Encoding.GetEncoding(950); // Chinese Traditional
    encRemoveAllBut = System.Text.Encoding.ASCII; // putting ASCII again, as to answer the question 
    
    // https://stackoverflow.com/questions/123336/how-can-you-strip-non-ascii-characters-from-a-string-in-c
    string inputString = "RäksmörПривет, мирgås";
    string asAscii = encRemoveAllBut.GetString(
        System.Text.Encoding.Convert(
            System.Text.Encoding.UTF8,
            System.Text.Encoding.GetEncoding(
                encRemoveAllBut.CodePage,
                new System.Text.EncoderReplacementFallback(string.Empty),
                new System.Text.DecoderExceptionFallback()
                ),
            System.Text.Encoding.UTF8.GetBytes(inputString)
        )
    );
    
    System.Console.WriteLine(asAscii);
    

    对于那些只想消除口音的人:
    (注意,因为 Normalize != Latinize != Romanize)

    // string str = Latinize("(æøå âôû?aè");
    public static string Latinize(string stIn)
    {
        // Special treatment for German Umlauts
        stIn = stIn.Replace("ä", "ae");
        stIn = stIn.Replace("ö", "oe");
        stIn = stIn.Replace("ü", "ue");
    
        stIn = stIn.Replace("Ä", "Ae");
        stIn = stIn.Replace("Ö", "Oe");
        stIn = stIn.Replace("Ü", "Ue");
        // End special treatment for German Umlauts
    
        string stFormD = stIn.Normalize(System.Text.NormalizationForm.FormD);
        System.Text.StringBuilder sb = new System.Text.StringBuilder();
    
        for (int ich = 0; ich < stFormD.Length; ich++)
        {
            System.Globalization.UnicodeCategory uc = System.Globalization.CharUnicodeInfo.GetUnicodeCategory(stFormD[ich]);
    
            if (uc != System.Globalization.UnicodeCategory.NonSpacingMark)
            {
                sb.Append(stFormD[ich]);
            } // End if (uc != System.Globalization.UnicodeCategory.NonSpacingMark)
    
        } // Next ich
    
    
        //return (sb.ToString().Normalize(System.Text.NormalizationForm.FormC));
        return (sb.ToString().Normalize(System.Text.NormalizationForm.FormKC));
    } // End Function Latinize
    

    【讨论】:

      猜你喜欢
      • 2012-04-28
      • 2012-01-21
      • 1970-01-01
      • 1970-01-01
      • 2018-10-21
      相关资源
      最近更新 更多