Я попытался написать метод замены строк, поддерживающий культуру:
public static string Replace(string text, string oldValue, string newValue)
{
int index = text.IndexOf(oldValue, StringComparison.CurrentCulture);
return index >= 0
? text.Substring(0, index) + newValue + text.Substring(index + oldValue.Length)
: text;
}
Однако он зажимает символы Unicode, комбинируя символы:
// \u0301 is Combining Acute Accent
Console.WriteLine(Replace("déf", "é", "o")); // 1. CORRECT: dof
Console.WriteLine(Replace("déf", "e\u0301", "o")); // 2. INCORRECT: do
Console.WriteLine(Replace("de\u0301f", "é", "o")); // 3. INCORRECT: dóf
Чтобы исправить мой код, мне нужно знать, что во втором примере String.IndexOf
соответствует только одному символу (é
), хотя он искал два (e\u0301
). Точно так же мне нужно знать, что в третьем примере String.IndexOf
соответствует двум символам (e\u0301
), хотя он искал только один (é
).
Как определить фактическую длину подстроки, которая соответствует String.IndexOf
?
ПРИМЕЧАНИЕ: Выполнение нормализации Юникода на text
и oldValue
(как было предложено Джеймсом Кизи) будет вмещать сочетание символов, но лигатуры все равно будут проблемой:
Console.WriteLine(Replace("œf", "œ", "i")); // 4. CORRECT: if
Console.WriteLine(Replace("œf", "oe", "i")); // 5. INCORRECT: i
Console.WriteLine(Replace("oef", "œ", "i")); // 6. INCORRECT: ief