Нужно чтобы в строке не было символа '\n'. Для этого:
1. Заменяем все "\\" на "\\\\".
2. Заменяем все "\n" на "\\n".
Это все понятно. Самый смак — как возвернуть все взад...
Накидал 5 вариантов, см. полный код:
class Program
{
static void Main(string[] args)
{
Random r = new Random();
var sb = new StringBuilder(2000000 * 7);
sb.Append("test1\ntest2\\n\\\\test3");
for (int i = 0; i < 2000000; i++)
{
if (r.Next(1, 3) == 1)
sb.Append("\\");
if (r.Next(1, 3) == 1)
sb.Append("\\");
if (r.Next(1, 3) == 1)
sb.Append("\\n");
if (r.Next(1, 4) == 3)
sb.Append("\n");
sb.Append("word");
}
var input = sb.ToString();
var escaped = input.Replace("\\", "\\\\").Replace("\n", "\\n");
var sw = new Stopwatch();
sw.Reset();
sw.Start();
//var unescaped = Test1(escaped);
//var unescaped = Test2(escaped);
//var unescaped = Test3(escaped);
//var unescaped = Test4(escaped);
var unescaped = Test5(escaped);
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
Console.ReadLine();
Console.WriteLine(unescaped.Equals(input));
}
static string Test1(string escaped)
{
var guid = Guid.NewGuid().ToString();
return escaped.Replace("\\\\", guid).Replace("\\n", "\n").Replace(guid, "\\");
}
static string Test2(string escaped)
{
return escaped.Split(new[] {"\\\\"}, StringSplitOptions.None)
.Aggregate((seed, next) => seed + "\\" + next.Replace("\\n", "\n"));
}
static string Test3(string escaped)
{
var parts = escaped.Split(new[] { "\\\\" }, StringSplitOptions.None).Select(part => part.Replace("\\n", "\n"));
return string.Join("\\", parts);
}
static string Test4(string escaped)
{
var unescaped = new StringBuilder(escaped.Length);
bool slash = false;
foreach (var ch in escaped)
{
if (slash)
{
if ('\\' == ch)
unescaped.Append('\\');
if ('n' == ch)
unescaped.Append('\n');
slash = false;
continue;
}
if ('\\' == ch)
slash = true;
else
unescaped.Append(ch);
}
return unescaped.ToString();
}
static string Test5(string escaped)
{
var unescaped = new StringBuilder(escaped.Length);
int currentIndex = 0;
while (true)
{
var slashIndex = escaped.IndexOf('\\', currentIndex);
if (-1 == slashIndex)
{
unescaped.Append(escaped, currentIndex, escaped.Length - currentIndex);
break;
}
unescaped.Append(escaped, currentIndex, slashIndex - currentIndex);
currentIndex = slashIndex;
var nextChar = escaped[slashIndex + 1];
switch (nextChar)
{
case '\\':
unescaped.Append('\\');
break;
case 'n':
unescaped.Append('\n');
break;
default:
throw new InvalidOperationException("nextChar=" + nextChar);
}
currentIndex++;
currentIndex++;
}
return unescaped.ToString();
}
}
Сокращенная версия для запуска:
https://dotnetfiddle.net/52uORv
И вопрос: как вы думаете, какой
вариант самый быстрый? Как сделать быстрее?