我在下面的帖子询问了弯引号是什么以及为什么我的应用程序无法使用它们,我现在的问题是当我的程序遇到它们时如何替换它们,我如何在 C# 中做到这一点?它们是特殊字符吗?
谢谢
我在下面的帖子询问了弯引号是什么以及为什么我的应用程序无法使用它们,我现在的问题是当我的程序遇到它们时如何替换它们,我如何在 C# 中做到这一点?它们是特殊字符吗?
谢谢
有问题的单词字符的更广泛列表
if (buffer.IndexOf('\u2013') > -1) buffer = buffer.Replace('\u2013', '-');
if (buffer.IndexOf('\u2014') > -1) buffer = buffer.Replace('\u2014', '-');
if (buffer.IndexOf('\u2015') > -1) buffer = buffer.Replace('\u2015', '-');
if (buffer.IndexOf('\u2017') > -1) buffer = buffer.Replace('\u2017', '_');
if (buffer.IndexOf('\u2018') > -1) buffer = buffer.Replace('\u2018', '\'');
if (buffer.IndexOf('\u2019') > -1) buffer = buffer.Replace('\u2019', '\'');
if (buffer.IndexOf('\u201a') > -1) buffer = buffer.Replace('\u201a', ',');
if (buffer.IndexOf('\u201b') > -1) buffer = buffer.Replace('\u201b', '\'');
if (buffer.IndexOf('\u201c') > -1) buffer = buffer.Replace('\u201c', '\"');
if (buffer.IndexOf('\u201d') > -1) buffer = buffer.Replace('\u201d', '\"');
if (buffer.IndexOf('\u201e') > -1) buffer = buffer.Replace('\u201e', '\"');
if (buffer.IndexOf('\u2026') > -1) buffer = buffer.Replace("\u2026", "...");
if (buffer.IndexOf('\u2032') > -1) buffer = buffer.Replace('\u2032', '\'');
if (buffer.IndexOf('\u2033') > -1) buffer = buffer.Replace('\u2033', '\"');
当我遇到这个问题时,我在 C# 中为 String 类编写了一个扩展方法。
public static class StringExtensions
{
public static string StripIncompatableQuotes(this string s)
{
if (!string.IsNullOrEmpty(s))
return s.Replace('\u2018', '\'').Replace('\u2019', '\'').Replace('\u201c', '\"').Replace('\u201d', '\"');
else
return s;
}
}
这只是用普通引号替换了愚蠢的“智能引号”。
[编辑] 修复了也支持替换“双智能引号”。
为了扩展 Nick van Esch 的流行答案,这里是注释中包含字符名称的代码。
if (buffer.IndexOf('\u2013') > -1) buffer = buffer.Replace('\u2013', '-'); // en dash
if (buffer.IndexOf('\u2014') > -1) buffer = buffer.Replace('\u2014', '-'); // em dash
if (buffer.IndexOf('\u2015') > -1) buffer = buffer.Replace('\u2015', '-'); // horizontal bar
if (buffer.IndexOf('\u2017') > -1) buffer = buffer.Replace('\u2017', '_'); // double low line
if (buffer.IndexOf('\u2018') > -1) buffer = buffer.Replace('\u2018', '\''); // left single quotation mark
if (buffer.IndexOf('\u2019') > -1) buffer = buffer.Replace('\u2019', '\''); // right single quotation mark
if (buffer.IndexOf('\u201a') > -1) buffer = buffer.Replace('\u201a', ','); // single low-9 quotation mark
if (buffer.IndexOf('\u201b') > -1) buffer = buffer.Replace('\u201b', '\''); // single high-reversed-9 quotation mark
if (buffer.IndexOf('\u201c') > -1) buffer = buffer.Replace('\u201c', '\"'); // left double quotation mark
if (buffer.IndexOf('\u201d') > -1) buffer = buffer.Replace('\u201d', '\"'); // right double quotation mark
if (buffer.IndexOf('\u201e') > -1) buffer = buffer.Replace('\u201e', '\"'); // double low-9 quotation mark
if (buffer.IndexOf('\u2026') > -1) buffer = buffer.Replace("\u2026", "..."); // horizontal ellipsis
if (buffer.IndexOf('\u2032') > -1) buffer = buffer.Replace('\u2032', '\''); // prime
if (buffer.IndexOf('\u2033') > -1) buffer = buffer.Replace('\u2033', '\"'); // double prime
请注意,您所拥有的本质上是一个损坏的 CSV 文件。不加选择地用直引号替换所有印刷者的引号不一定会修复您的文件。如您所知,作为字段值的一部分,一些排版员的引用应该在那里。用直引号替换它们可能也不会给您留下有效的 CSV 文件。
我认为没有一种算法方法可以修复按照您描述的方式损坏的文件。您最好先花时间调查一下您是如何获得此类无效文件的,然后再制止它。例如,有人使用 Word 来编辑您的数据文件吗?
我有一个很棒的大...程序...正是这样做的。您可以撕下脚本并随意使用它。它进行各种替换,位于http://bitbucket.org/nesteruk/typografix
根据 Windows 附带的 Character Map 应用程序,大括号的 Unicode 值是 0x201c 和 0x201d。用直引号 0x0022 替换这些值,你应该很高兴。
String.Replace(0x201c, '"');
String.Replace(0x201d, '"');
VB 相当于@Matthew 所写的内容:
Public Module StringExtensions
<Extension()>
Public Function StripIncompatableQuotes(BadString As String) As String
If Not String.IsNullOrEmpty(BadString) Then
Return BadString.Replace(ChrW(&H2018), "'").Replace(ChrW(&H2019), "'").Replace(ChrW(&H201C), """").Replace(ChrW(&H201D), """")
Else
Return BadString
End If
End Function
End Module
如果上述方法不起作用,请尝试使用智能单引号:
string.Replace("\342\200\230", "'")
string.Replace("\342\200\231", "'")
也可以试试这个智能双引号:
string.Replace("\342\200\234", '"')
string.Replace("\342\200\235", '"')
我也有一个程序可以做到这一点,源代码在这个CP-1252 Fixer文件中。它还定义了一些映射,用于在 RTF 字符串中转换字符,同时保留所有格式,这可能对某些人有用。
它也是所有“智能引用”字符到它们的低 ascii 对应物、实体代码和字符引用的完整映射。
只是插话,我用 Regex replace 完成了这个,只是为了根据我替换它们的内容一次处理几个:
public static string ReplaceWordChars(this string text)
{
var s = text;
// smart single quotes and apostrophe, single low-9 quotation mark, single high-reversed-9 quotation mark, prime
s = Regex.Replace(s, "[\u2018\u2019\u201A\u201B\u2032]", "'");
// smart double quotes, double prime
s = Regex.Replace(s, "[\u201C\u201D\u201E\u2033]", "\"");
// ellipsis
s = Regex.Replace(s, "\u2026", "...");
// em dashes
s = Regex.Replace(s, "[\u2013\u2014]", "-");
// horizontal bar
s = Regex.Replace(s, "\u2015", "-");
// double low line
s = Regex.Replace(s, "\u2017", "-");
// circumflex
s = Regex.Replace(s, "\u02C6", "^");
// open angle bracket
s = Regex.Replace(s, "\u2039", "<");
// close angle bracket
s = Regex.Replace(s, "\u203A", ">");
// weird tilde and nonblocking space
s = Regex.Replace(s, "[\u02DC\u00A0]", " ");
// half
s = Regex.Replace(s, "[\u00BD]", "1/2");
// quarter
s = Regex.Replace(s, "[\u00BC]", "1/4");
// dot
s = Regex.Replace(s, "[\u2022]", "*");
// degrees
s = Regex.Replace(s, "[\u00B0]", " degrees");
return s;
}
那里还有一些替代品。
使用尼克和芭芭拉的答案,这里是我的机器上 1,000,000 次循环的性能统计的示例代码:
input = "shmB6BhLe0gdGU8OxYykZ21vuxLjBo5I1ZTJjxWfyRTTlqQlgz0yUtPu8iNCCcsx78EPsObiPkCpRT8nqRtvM3Bku1f9nStmigaw";
input.Replace('\u2013', '-'); // en dash
input.Replace('\u2014', '-'); // em dash
input.Replace('\u2015', '-'); // horizontal bar
input.Replace('\u2017', '_'); // double low line
input.Replace('\u2018', '\''); // left single quotation mark
input.Replace('\u2019', '\''); // right single quotation mark
input.Replace('\u201a', ','); // single low-9 quotation mark
input.Replace('\u201b', '\''); // single high-reversed-9 quotation mark
input.Replace('\u201c', '\"'); // left double quotation mark
input.Replace('\u201d', '\"'); // right double quotation mark
input.Replace('\u201e', '\"'); // double low-9 quotation mark
input.Replace("\u2026", "..."); // horizontal ellipsis
input.Replace('\u2032', '\''); // prime
input.Replace('\u2033', '\"'); // double prime
时间:958.1011 毫秒
input = "shmB6BhLe0gdGU8OxYykZ21vuxLjBo5I1ZTJjxWfyRTTlqQlgz0yUtPu8iNCCcsx78EPsObiPkCpRT8nqRtvM3Bku1f9nStmigaw";
var inputArray = input.ToCharArray();
for (int i = 0; i < inputArray.Length; i++)
{
switch (inputArray[i])
{
case '\u2013':
inputArray[i] = '-';
break;
// en dash
case '\u2014':
inputArray[i] = '-';
break;
// em dash
case '\u2015':
inputArray[i] = '-';
break;
// horizontal bar
case '\u2017':
inputArray[i] = '_';
break;
// double low line
case '\u2018':
inputArray[i] = '\'';
break;
// left single quotation mark
case '\u2019':
inputArray[i] = '\'';
break;
// right single quotation mark
case '\u201a':
inputArray[i] = ',';
break;
// single low-9 quotation mark
case '\u201b':
inputArray[i] = '\'';
break;
// single high-reversed-9 quotation mark
case '\u201c':
inputArray[i] = '\"';
break;
// left double quotation mark
case '\u201d':
inputArray[i] = '\"';
break;
// right double quotation mark
case '\u201e':
inputArray[i] = '\"';
break;
// double low-9 quotation mark
case '\u2026':
inputArray[i] = '.';
break;
// horizontal ellipsis
case '\u2032':
inputArray[i] = '\'';
break;
// prime
case '\u2033':
inputArray[i] = '\"';
break;
// double prime
}
}
input = new string(inputArray);
时间:362.0858 毫秒
它对我有用,你可以试试下面的代码
string replacedstring = ("your string with smart quotes").Replace('\u201d', '\'');
谢谢!