#c_sharp #регулярные_выражения
Нужно сделать регулярное выражение, которое будет удалять предыдущий символ перед текстом. Казалось бы, это реализуется очень просто: str = Regex.Replace(str, @". ", ""); Но тут есть подводные камни. Если, например, в тексте идет 2 подряд, тогда конструкция рушится. Можно, конечно, сделать такое решение: str = Regex.Replace(str, @". |.. ", ""); но это бред, ведь может быть и 10 подряд и надо будет удалить 10 предыдущих символов. Как сделать универсальным это регулярное выражение? Может быть такая строка: string str = "это буу дка ет тек стовыыф й ткаукц екст"; В итоге должны получить: "это будет тестовый текст"
Ответы
Ответ 1
Думаю, одной изящной регуляркой это не сделать. Я придумал следующее: Match m; do { m = Regex.Match(str, "."); str = str.Remove(m.Index, m.Length); } while (m.Success); В цикле находим и удаляем по одному вхождению паттерна. Конечно, этот способ не блещет производительностью. Ответ 2
В .NET можно решить эту проблему регулярным выражением с проверкой состояния стека захватывающих групп: ^(?:)+|(?:(? (? ))+(?(t)(?!))(?: )* См. демо регулярного выражения. Подробности ^(?: )+ - один и более последовательностей символов в начале строки (^) | - или (?:(? (? ))+ - незахватывающая группа ((?:...)), находящая одну или более (+ — жадный квантификатор, находит 1 и более последовательных совпадений) последовательностей (? (? ): (? (? ) - одна и более последовательностей символов (при этом каждый раз при найденном совпадении из стека группы t будет удаляться последнее значение) (?(t)(?!)) - условная конструкция: если стек группы t не пуст, совпадение считается неверным, и запускается поиск с возвратом (backtracking), иначе возвращается совпадение (такое, где количество значений, найденных (? .) равно количеству значений, найденных (?<-t> )) (?: )* - ноль и более последовательностей символов Можно объявить это выражение в коде следующим образом: public static class Rx { public static readonly Regex backspaceRx = new Regex( @"^(?: )+ # 1+ в начале | # или (?: (? (? ) # )+ # 1 или более раз (?(t)(?!)) # проверка стека группы t (?: )* # 0+ ", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace); } Тест на C#: var tests = new List {" это буу дка ет тек стовыыф й ткаукц екст", "Это ", "a b", " ", "ab c d" }; foreach(var test in tests) Console.WriteLine("'{0}'", Rx.backspaceRx.Replace(test, string.Empty)); Вывод: 'это будет тестовый текст' '' 'b' '' 'd'
Комментариев нет:
Отправить комментарий