Я попытался написать метод замены строк, поддерживающий культуру:
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