Но Linq-to-Regex должен был существовать, по следующим причинам:
1. Регулярное выражение, особенно не банальное [A-Za-z0-9]+ - штука довольно сложная для визуального восприятия.
2. Regex'ы - это идеальное вместилище для труднопрогнозируемых ошибок из серии "очепятка". А шарп по своей идеологии категорически не должен такое разрешать.
3. Regex'ы как класс реализованы в C# и .Net отвратительно, совершенно не встроены в язык, поддерживают очень мало полезных фишек... И несмотря на то, что я обожаю перл, и обожаю перловые регексы, и нет, наверное, ни одного скрипта на перле, где бы я их не использовал - несмотря на всё это, за все те 3 года, которые я пишу на C#, я юзал шарповые Regex'ы ну может раз 5-6 (причем, чаще всего в валидаторах, и регексы чаще всего были крайне примитивными)...
Осознав это, и зная, что Linq действительно хорошо решает задачи упрощения кода, (вместе с тем делая его более строгим и типизированным, шарповым), смело набрал эту фразу в гугле. И не ошибся, попытка создать Linq-to-Regex действительно была. Полюбуйтесь примером:
[Test] public void FindEmailUsingPattern() { var query = from match in RegexQuery.Against("sdlfjsfl43r3490r98*(*Email@somewhere.com_dakj3j") where match.Word.Repeat.AtLeast(1) .Literal("@") .Word.Repeat.AtLeast(1) .Literal(".") .Choice.Either( Pattern.With.Literal("com"), Pattern.With.Literal("net")) .IsTrue() select match; foreach (var match in query) { Assert.AreEqual("Email@somewhere.com",match.Value); } }К сожалению, при ближайшем рассмотрении, выяснилось, что линка как такового тут почти и нет. Пожалуй, в данном случае мы имеем как раз с тем, что ребята из пальца высасывали эту связку. В большей степени мы тут видим просто некий fluent interface, и то, на мой взгляд, неудачный. Но здесь дело даже не в нём (на самом деле есть более удачный вариант). Дело в неверном подходе.
Мне кажется, авторы Linq-to-Regex слишком зацикливались на самом названии, "Linq-to-Regex". Не нужен в C# регекс как таковой. Нужен просто его адекватный заменитель. Стандартный Linq уже может оперировать строкой как IEnumerable<char>, но не позволяет многих фишек, на которые способен Regex.
Основные фишки регекса следующие:
- определение паттерна текста из нескольких следующих друг за другом символов из выбранного диапазона
- определение паттерна текста как некой последовательности статических символов
- группировка паттернов и вытаскивание этих групп из исходной строки
- развилки ("|")
- всякие условия и флаги, типа совпадения начиная с начала строки
Я набросал примерчик, как это могло бы выглядеть:
// примерный аналог регекса // [A-Za-z]+[A-Za-z0-9\.\-_]*@[A-Za-z]+[A-Za-z0-9\.\-_]*\.[A-Za-z]{2,4} // должно вернуть "dkd.ru@man-r.na" StringMatch[] matches = "ldskfj@dnfnf#dkd.ru@man-r.na,dlr" .StartMatch() .MatchChars(c => Char.IsLetter(ch), CharsCount.Once) .MatchChars(c => Char.IsLetterOrDigit(ch) || new char[] { '_', '.', '-' }.Contains(ch), CharsCount.NeverOrMore) .MatchChars(c => c == "@", CharsCount.Once), .MatchChars(c => Char.IsLetter(ch), CharsCount.Once) .MatchChars(c => Char.IsLetterOrDigit(ch) || new char[] { '_', '.', '-' }.Contains(ch), CharsCount.NeverOrMore) .MatchChars(c => c == ".", CharsCount.Once) .MatchChars(c => Char.IsLetter(ch), new CharMatchBounds(2, 4)) .EndMatch();На мой взгляд, подобным этому синтаксисом уже можно будет более-менее пользоваться... И неважно что писать долго, зато разобраться можно, ошибки легко отлавливаются, есть интеллисенс, magic symbols не используются и т.д.
Но то, что есть сейчас - это какой-то нелепый пришлепок, в самом деле... Не для шарпа.
да, регэкспы - это больная тема
ОтветитьУдалить