Как сделать замену с учетом нескольких регистров, используя StringBuilder
У меня есть (большой) шаблон и я хочу заменить несколько значений. Замена должна быть сделана без учета регистра. Также должна быть возможность иметь ключи, которых нет в шаблоне.
Например:
[TestMethod]
public void ReplaceMultipleWithIgnoreCaseText()
{
const string template = "My name is @Name@ and I like to read about @SUBJECT@ on @website@, tag @subject@";
const string expected = "My name is Alex and I like to read about C# on stackoverflow.com, tag C#";
var replaceParameters = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("@name@","Alex"),
new KeyValuePair<string, string>("@subject@","C#"),
new KeyValuePair<string, string>("@website@","stackoverflow.com"),
// Note: The next key does not exist in template
new KeyValuePair<string, string>("@country@","The Netherlands"),
};
var actual = ReplaceMultiple(template, replaceParameters);
Assert.AreEqual(expected, actual);
}
public string ReplaceMultiple(
string template,
IEnumerable<KeyValuePair<string, string>> replaceParameters)
{
throw new NotImplementedException(
"Implementation needed for many parameters and long text.");
}
Обратите внимание, что если у меня есть список из 30 параметров и большой шаблон, я не хочу 30 больших строк в памяти. Использование StringBuilder представляется возможным, но приветствуются и другие решения.
Решение, которое я пробовал, но не сработало
Решение найдено здесь (C # String заменить на словарь) создает исключение, когда ключ отсутствует в коллекции, но наши пользователи допускают ошибки, и в этом случае я хочу просто оставить ключ wromg в тексте. Пример:
static readonly Regex re = new Regex(@"\$(\w+)\$", RegexOptions.Compiled);
static void Main2()
{
// "Name" is accidentally typed by a user as "nam".
string input = @"Dear $nam$, as of $date$ your balance is $amount$";
var args = new Dictionary<string, string>(
StringComparer.OrdinalIgnoreCase) {
{"name", "Mr Smith"},
{"date", "05 Aug 2009"},
{"amount", "GBP200"}};
// Works, but not case insensitive and
// uses a lot of memory when using a large template
// ReplaceWithDictionary many args
string output1 = input;
foreach (var arg in args)
{
output1 = output1.Replace("$" + arg.Key +"$", arg.Value);
}
// Throws a KeyNotFoundException + Only works when data is tokenized
string output2 = re.Replace(input, match => args[match.Groups[1].Value]);
}