С# Как заменить смарт-кавычки Microsoft прямыми кавычками?

В моем сообщении ниже спрашивалось, что такое фигурные кавычки и почему мое приложение не будет работать с ними, теперь мой вопрос заключается в том, как я могу заменить их, когда моя программа сталкивается с ними, как я могу сделать это в С#? Являются ли они специальными символами?

curly-quotation-marks-vs-square-quotation-marks- что дает

Спасибо


person Community    schedule 02.12.2008    source источник
comment
Типографские кавычки не менее реальны, чем прямые кавычки.   -  person Rob Kennedy    schedule 02.12.2008


Ответы (12)


Более обширный список проблемных словесных символов

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', '\"');
person Nick van Esch    schedule 05.02.2010
comment
Мне любопытно, кто-нибудь проводил тестирование производительности, которое показывает, что .IndexOf() дешевле, чем запуск .Replace() для строки, которая не содержит символ? - person Ted A.; 15.05.2014
comment
Самой дешевой операцией будет повторение строки один раз, а не повторение, возможно, до 2 * количество адресованных символов. Например: foreach(char c in buffer) { /* if char in list to be replaced, replace */ }. - person Dan; 19.01.2015
comment
Я с Тедом А. здесь ... buffer.Replace в любом случае должен делать по существу эквивалент buffer.IndexOf внутри; Я не могу представить себе никаких обстоятельств, при которых вызов if-test и IndexOf улучшит ситуацию. НО, это выглядит как отличный список замен, так что спасибо! - person Joe Strout; 27.04.2018
comment
Очень полезный список, хотя u201f (двойная кавычка вверх-9) отсутствует. - person Moo; 23.05.2019

Когда я столкнулся с этой проблемой, я написал метод расширения для класса String на C#.

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;
    }
}

Это просто заменяет глупые «умные кавычки» обычными кавычками.

[EDIT] Исправлена ​​поддержка замены «двойных умных кавычек».

person Matthew Ruston    schedule 02.12.2008

Чтобы расширить популярный ответ Ника ван Эша, вот код с именами персонажей в комментариях.

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
person Barbara from Boston    schedule 15.05.2015
comment
Привет Барбара. Полезное дополнение к ответу, но это лучше подходит в качестве предлагаемого редактирования существующего ответа, а не нового. - person user247702; 15.05.2015
comment
@Barbara, привет, нет ли метода, который может заменить все символы без указания каждого символа вручную. Если в дальнейшем в коде, кроме указанных выше, появятся и другие символы, то? - person Anish Mittal; 28.07.2017
comment
Это текущее требование в нашем случае. Любой специальный символ из файла MS Word может прийти, и он должен быть преобразован в прямой символ и отображаться правильно. - person Anish Mittal; 28.07.2017

Обратите внимание, что у вас есть поврежденный файл CSV. Замена без разбора всех типографских кавычек прямыми кавычками не обязательно исправит ваш файл. Насколько вы знаете, некоторые кавычки типографа должны были быть там как часть значения поля. Замена их прямыми кавычками также может не оставить вам действительный CSV-файл.

Я не думаю, что есть алгоритмический способ исправить файл, который поврежден так, как вы описываете. Ваше время может быть лучше потрачено на изучение того, как вы получили такие недействительные файлы, а затем на то, чтобы положить этому конец. Например, кто-то использует Word для редактирования ваших файлов данных?

person Rob Kennedy    schedule 02.12.2008
comment
Эм, я не думаю, что этот вопрос имеет какое-либо отношение к файлам CSV... :) - person AR.; 03.12.2008
comment
Нет, но вопрос, на который ссылается OP, делает. - person GalacticCowboy; 03.12.2008

Согласно приложению «Карта символов», которое поставляется с Windows, значения Unicode для фигурных кавычек — 0x201c и 0x201d. Замените эти значения прямой кавычкой 0x0022, и все будет хорошо.

String.Replace(0x201c, '"');
String.Replace(0x201d, '"');
person Mark Ransom    schedule 02.12.2008

Эквивалент 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
person cjbarth    schedule 19.04.2013

У меня есть целая большая... программа... которая делает именно это. Вы можете выдрать сценарий и использовать его на свое усмотрение. Он выполняет все виды замен и находится по адресу http://bitbucket.org/nesteruk/typografix.

person Dmitri Nesteruk    schedule 02.12.2008

У меня также есть программа, которая делает это, источник находится в этот файл фиксатора CP-1252. Кроме того, он определяет некоторые сопоставления для преобразования символов в строках RTF с сохранением всего форматирования, что может быть полезно для некоторых.

Это также полное сопоставление всех символов "умных кавычек" с их аналогами в низком коде ASCII, кодами сущностей и ссылками на символы.

person pospi    schedule 15.04.2011

Попробуйте это для умных одинарных кавычек, если вышеперечисленное не работает:

string.Replace("\342\200\230", "'")
string.Replace("\342\200\231", "'")

Попробуйте это и для умных двойных кавычек:

string.Replace("\342\200\234", '"')
string.Replace("\342\200\235", '"')
person Community    schedule 05.02.2010

это сработало для меня, вы можете попробовать код ниже

string replacedstring = ("your string with smart quotes").Replace('\u201d', '\'');

Спасибо!

person Asif Ghanchi    schedule 20.04.2017

Используя ответы Ника и Барбары, вот пример кода со статистикой производительности для 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 миллисекунды

person Taylor Wallgren    schedule 06.07.2018

просто вклиниваюсь, я сделал это с заменой Regex, чтобы обрабатывать несколько за раз в зависимости от того, на что я их заменяю:

        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;
        }

Там же еще несколько замен.

person Ed Cayce    schedule 14.11.2019