如何从字符串中去除非 ASCII 字符? (在 C# 中)
Posted
技术标签:
【中文标题】如何从字符串中去除非 ASCII 字符? (在 C# 中)【英文标题】:How can you strip non-ASCII characters from a string? (in C#) 【发布时间】:2010-09-12 12:10:21 【问题描述】:【问题讨论】:
根据 sinelaw 的回答 below,如果您想替换非 ASCII 字符,请参阅 this answer。 【参考方案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 => c >= min && c <= 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\\:_\- ]", "")
这应该是文件名允许的所有字符。
【讨论】:
不。请参阅 Path.GetInvalidPathChars 和 Path.GetInvalidFileNameChars。因此,有数万个有效字符。 你是对的,汤姆。我实际上是在考虑常见的,但我忽略了括号和花括号以及所有这些 - ^%$#@!&+=。【参考方案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://***.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
【讨论】:
以上是关于如何从字符串中去除非 ASCII 字符? (在 C# 中)的主要内容,如果未能解决你的问题,请参考以下文章