2016-12-08 2 views
3

Есть ли у вас какие-либо идеи или советы, как безопасно заменить строку?C# String Replace безопасно

Пример:

string Example = "OK OR LOK"; 

Теперь я хочу, чтобы заменить "OK" с истинным и "ЛОК" с ложными.

Example = Example.Replace("OK", "true"); 
Example = Example.Replace("LOK", "false"); 

Сейчас Результат: Example = "true or Ltrue";

Результат должен быть: Example ="true or false";

Я понимаю проблему, но я понятия не имею, как это исправить.

Благодаря

+8

Сначала замените LOK, затем OK, потому что OK является подмножеством LOK – BugFinder

+0

@BugFinder - отличное наблюдение и обзор. – jignesh

+1

Другой вариант - замена на основе регулярных выражений. – Dai

ответ

5

Вы могли бы сначала заменить длинные строки, F.E. с помощью этого метода:

public static string ReplaceSafe(string str, IEnumerable<KeyValuePair<string, string>> replaceAllOfThis) 
{ 
    foreach (var kv in replaceAllOfThis.OrderByDescending(kv => kv.Key.Length)) 
    { 
     str = str.Replace(kv.Key, kv.Value); 
    } 
    return str; 
} 

Вашего пример:

Example = ReplaceSafe(Example, new[] {new KeyValuePair<string, string>("OK", "true"), new KeyValuePair<string, string>("LOK", "false")}); 
+0

хороший!этот код также исправил эту проблему: string Example = "test OR test 2"; –

4
Example = Example.Replace("LOK", "false").Replace("OK", "true"); 
1

Это может быть накладными расходами для такой задачи, но вот версия с использованием регулярных выражений с отрицательным просмотром назад:

string Example = "OK OR LOK"; 
// Replace "OK" which is not preceded by any word character 
string res = Regex.Replace(Example, @"(?<!\w)OK", "true"); 
string res2 = Regex.Replace(res, @"(?<!\w)LOK", "false"); 

Console.WriteLine(res); 
Console.WriteLine(res2); 

EDIT: вдохновленный @ Джон Ханна.

если OK или ЛКИ должны иметь хвост, как ОЭК или ШЛЮЗЫ положительный looakhead для пространства (\s) или в конце строки ($) может решить эту проблему:

string res = Regex.Replace(Example, @"(?<!\w)OK(?=[\s|$])", "true"); 
string res2 = Regex.Replace(res, @"(?<!\w)LOK(?=[\s|$])", "false"); 
+0

Что происходит с «ОКЕ»? –

+0

@JonHanna хорошая точка, сделанная редактировать –

+1

'\ b' полезен здесь. Он соответствует границе между символами слова и символами не-слов, или началом и концом строки без необходимости просмотра. –

2

Вы могли бы искать «ЛКИ «во-первых, но это не поможет с более общей проблемой не соответствия« POKE »и производства« PtrueE »и т. д.

следующие взгляды на границы слов:

new Regex(@"\bLOK\b").Replace(
    new Regex(@"\bOK\b").Replace("OK OR LOK", "true"), 
    "false") 

Более гибкий подход снова к обоим искать границы слов и определить, какие замены один делает в матче-оценщиком:

new Regex(@"\bLOK|OK\b").Replace("OK OR LoK", m => 
{ 
    switch(m.Value) 
    { 
    case "OK": 
     return "true"; 
    default: 
     return "false"; 
    } 
}) 

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

+0

нормально работает нормально, но если я хочу это сделать, ничего не произойдет: строка ОК = «ОК»; string replace = new Regex (@ "\ b" + OK + "\ b"). Заменить (пример, "true"); –

+0

Ваш второй '' \ b "' - это код для символа обратного пробела, он должен быть '@" \ b "' или '" \\ b "'. Кроме того, если вы строите динамически, вы должны использовать '@" \ b "+ Regex.Escape (OK) + @" \ b "' таким образом, если ваша строка поиска ('OK') содержит любые символы, которые специальные в регулярных выражениях они экранируются в соответствии с фактическим символом. –