Когда лучше использовать Регулярные выражения над базовым разбиением строки / подстрокой?

Кажется, что выбор использования парсинга строк по сравнению с регулярными выражениями возникает у меня на регулярной основе каждый раз, когда возникает ситуация, когда мне нужна часть строки, информация о указанной строке и т. Д.

Причина этого заключается в том, что мы оцениваем действие мыльного заголовка после того , как оно было проанализировано во что-то управляемое через объект OperationContext для WCF, а затем принимаем решения по нему. Прямо сейчас, простое решение, кажется, является основной подстрокой, чтобы сохранить реализацию простой, но часть меня интересует, будет ли RegEx лучше или надежнее. Другая часть меня задается вопросом, будет ли это похоже на использование дробовика, чтобы убить муху в нашем конкретном сценарии.

Поэтому я должен спросить, каков типичный порог, который используют люди, когда пытаются решить использовать RegEx вместо обычного анализа строк. Обратите внимание, что я не очень силен в Регулярных выражениях, и из-за этого я стараюсь уклоняться, если абсолютно не нужно избегать усложнения, чем мне нужно.

Если вы не можете сказать по моему выбору сокращений, это в .NET Land (C #), но я считаю, что это не имеет большого отношения к этому вопросу.


РЕДАКТИРОВАТЬ : Кажется, в соответствии с моим типичным обаянием Raybell, я был слишком многословным или вводящим в заблуждение в моем вопросе. Я хочу попросить прощения. Я давал некоторые сведения, чтобы помочь понять, что я делаю, а не вводить людей в заблуждение.

Я в основном ищу руководство относительно того, когда использовать подстроку и ее варианты, по регулярным выражениям и наоборот. И хотя некоторые из ответов, возможно, пропустили это (и снова моя вина), я искренне оценил их и проголосовал соответственно.

10.12.2008 22:21:35
Если вы не говорите иначе, я думаю, что этот вопрос отвечает на тот же вопрос, который вы задаете: stackoverflow.com/questions/56342/…
EBGreen 10.12.2008 22:58:30
Это близко к тому, что я искал. Я искал, но так и не нашел ничего, что мне показалось подходящим, хотя это кажется таким же близким, как и все остальное.
Steven Raybell 10.12.2008 23:02:53
Я думаю, что я спрашиваю, если этот вопрос дает вам информацию, которую вы искали?
EBGreen 10.12.2008 23:04:52
Вроде, но, похоже, у меня есть лучший ответ ниже и, вероятно, скоро его приму.
Steven Raybell 10.12.2008 23:06:07
7 ОТВЕТОВ
РЕШЕНИЕ

Моим основным правилом является использование регулярных выражений для одноразового кода и для проверки пользовательского ввода. Или когда я пытаюсь найти определенный шаблон в большой части текста. Для большинства других целей я напишу грамматику и реализую простой парсер.

Одна важная рекомендация (от которой трудно обойтись, хотя я вижу, что люди все время пытаются это сделать) - всегда использовать парсер в случаях, когда грамматика целевого языка является рекурсивной.

Например, рассмотрим крошечный «язык выражений» для оценки заключенных в скобки арифметических выражений. Примеры «программ» на этом языке выглядят так:

1 + 2
5 * (10 - 6)
((1 + 1) / (2 + 2)) / 3

Грамматику легко написать, и она выглядит примерно так:

DIGIT := ["0"-"9"]
NUMBER := (DIGIT)+
OPERATOR := ("+" | "-" | "*" | "/" )
EXPRESSION := (NUMBER | GROUP) (OPERATOR EXPRESSION)?
GROUP := "(" EXPRESSION ")"

С помощью этой грамматики вы можете быстро создать парсер рекурсивного спуска.

ДЕЙСТВИТЕЛЬНО трудно написать эквивалентное регулярное выражение , потому что регулярные выражения обычно не очень хорошо поддерживают рекурсию.

Другим хорошим примером является прием JSON. Я видел, как люди пытаются использовать JSON с регулярными выражениями, и это безумие. Объекты JSON являются рекурсивными, поэтому они просто требуют регулярных грамматик и анализаторов рекурсивного спуска.


Хммммм ... Глядя на ответы других людей, я думаю, что, возможно, ответил не на тот вопрос.

Я интерпретировал это как "когда следует использовать использовать регулярное выражение, а не полноценный парсер?" в то время как большинство людей, по-видимому, интерпретируют вопрос как «когда вы должны использовать собственную неуклюжую специальную схему посимвольной проверки символов вместо использования регулярного выражения?»

Учитывая эту интерпретацию, мой ответ: никогда.


Ладно .... еще одно редактирование.

Я буду немного больше прощать схему «кати себе». Просто ... не называйте это "разбором": о)

Я думаю, что хорошее практическое правило заключается в том, что вы должны использовать примитивы, совпадающие со строками, только если вы можете реализовать ВСЕ свою логику, используя один предикат. Нравится:

if (str.equals("DooWahDiddy")) // No problemo.

if (str.contains("destroy the earth")) // Okay.

if (str.indexOf(";") < str.length / 2) // Not bad.

Как только ваши условия содержат несколько предикатов, вы начали изобретать свой собственный язык проверки строк ad hoc, и вам, вероятно, стоит просто разобраться и изучить некоторые регулярные выражения.

if (str.startsWith("I") && str.endsWith("Widget") &&
    (!str.contains("Monkey") || !str.contains("Pox")))  // Madness.

Регулярные выражения на самом деле не так сложно выучить. По сравнению с таким полнофункциональным языком, как C # с десятками ключевых слов, примитивных типов и операторов, и стандартной библиотекой с тысячами классов, регулярные выражения абсолютно просты. Большинство реализаций регулярных выражений поддерживают около дюжины или около того операций (уступать или брать).

Вот отличная ссылка:

http://www.regular-expressions.info/

PS: В качестве бонуса, если вы когда - нибудь действительно хотите узнать о написании собственных парсеров (с Лексом / Yacc, ANTLR, JavaCC, или другие аналогичные инструменты), изучение регулярных выражений является отличным препаратом, потому что инструмент анализатор-генератор использовать многие одни и те же принципы.

23
11.12.2008 15:41:43
У меня сложилось впечатление, что «базовый разбор строк» ​​подразумевает такие вещи, как вызовы 1 .indexOf () и 2 .subString () или что-то подобное. Для таких сложных вещей, я бы определенно пошел по пути парсера.
Joachim Sauer 10.12.2008 22:41:07
Я не обязательно делаю посимвольную проверку. Я просто хочу взять подстроку, а затем действовать по этому. В общем, я ищу общие рекомендации по выбору подстроки над регулярным выражением. Я полагаю, что я, возможно, не был очень ясен в своем вопросе ...
Steven Raybell 10.12.2008 22:47:40
Таким образом, из всех них, после вашей недавней правки, это в основном то, что я искал. Спасибо!
Steven Raybell 10.12.2008 23:08:39
Рад, что я мог быть (в конечном итоге) помощь!
benjismith 10.12.2008 23:10:04
С вами в целом "настоящий парсер" - почему люди так боятся грамматики?
Draemon 10.12.2008 23:44:34

Регулярное выражение может быть

  • легче понять
  • выразить более четко намерение
  • намного короче
  • легче изменить / адаптировать

В некоторых ситуациях все эти преимущества могут быть достигнуты с помощью регулярного выражения, в других достигаются только некоторые (например, регулярное выражение не очень легко понять), а в других ситуациях регулярное выражение труднее понять, затеняет намерение, дольше и трудно изменить.

Чем больше из этих (и, возможно, других) преимуществ я получаю от регулярного выражения, тем больше у меня шансов использовать их.

Возможное практическое правило: если понимание регулярного выражения потребует минут для кого-то, кто немного знаком с регулярными выражениями, то вы не захотите его использовать (если только «нормальный» код не станет еще более запутанным ;-).

Хм ... все еще нет простого эмпирического правила, извините.

6
10.12.2008 22:27:30

Когда требуемая трансформация не является базовой, но концептуально проста.

например, нет смысла вытягивать Regex, если вы делаете прямую замену строки ... проще использовать строку.

с другой стороны, сложное правило со многими условными или особыми случаями, которое может занять более 50 символов регулярного выражения, может стать кошмаром для последующего обслуживания, если вы не напишите его явно

1
10.12.2008 22:28:46

Я всегда использовал бы регулярное выражение, если это не что-то очень простое, например, разделение запятой строки. Если я думаю, что в один прекрасный день строки могут стать более сложными, я, вероятно, начну с регулярного выражения.

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

Регулярные выражения редко бывают лишними - если совпадение простое, то и регулярное выражение.

0
10.12.2008 22:32:55
Даже что-то CSV-парсер обманчиво сложно написать, учитывая правила цитирования. (Символы новой строки и запятые могут появляться в одном поле, если поле заключено в кавычки.) Не стоит недооценивать скромный CSV !!! Даже с регулярным выражением действительно трудно разобрать правильно: o)
benjismith 10.12.2008 23:06:29
Я сказал разделенную запятыми строку, а не файл CSV. Я бы никогда не порекомендовал ничего, кроме специальной библиотеки или анализатора для файла CSV. Я на самом деле написал C ++ CSV-парсер, который справился со всем вышеперечисленным, но мой отец был DFA
Draemon 10.12.2008 23:41:20

[W] мы оцениваем действия мыла и принимаем решения по этому вопросу

Никогда не используйте регулярные выражения или синтаксический анализ строк для обработки XML. В настоящее время каждый широко используемый язык имеет отличную поддержку XML. XML - обманчиво сложный стандарт, и вряд ли ваш код будет правильным в том смысле, что он будет правильно анализировать все правильно сформированные входные данные XML, и даже если это так, вы тратите свое время, потому что (как только что упоминалось) каждый язык в общее использование имеет поддержку XML. Непрофессионально использовать регулярные выражения для разбора XML.

Чтобы ответить на ваш вопрос, в целом использование регулярных выражений должно быть сведено к минимуму, поскольку они не очень читабельны. Часто вы можете объединить разбор строк и регулярные выражения (возможно, в цикле), чтобы создать гораздо более простое решение, чем одни только регулярные выражения.

2
10.12.2008 22:33:25
Я немного вводил в заблуждение и прошу прощения. Реальность такова, что к тому времени, когда мы с этим разбираемся, он был проанализирован для нас через OperationContext. Я благодарю вас за указание на это, хотя!
Steven Raybell 10.12.2008 22:43:15
Я немного обновил вопрос, чтобы улучшить ясность, но мне кажется, что он все еще сбивает с толку. Я переделаю это немного больше, когда у меня будет больше времени. Приношу извинения.
Steven Raybell 10.12.2008 22:48:16
Сожалею. Возможно, я мог бы быть более вежливым, но это то, что сводит меня с ума каждый раз, когда я это вижу.
Tmdean 10.12.2008 22:50:17
О, не беспокойся! Я прямо там с тобой. Там правильный инструмент для правильной работы. Не нужно во мне воссоздавать колесо или парсер, как это может быть.
Steven Raybell 10.12.2008 22:55:54

Я бы согласился с тем, что сказал Бенджизм, но хочу уточнить немного. Для очень простых синтаксисов простой синтаксический анализ строки может работать хорошо, но также могут и регулярные выражения. Я бы не назвал их излишними. Если это работает, это работает - иди с тем, что ты считаешь самым простым. И для парсинга строки от среднего до среднего, обычно используется регулярное выражение.

Как только вы начнете обнаруживать, что вам необходимо определить грамматику, то есть сложный синтаксический разбор строк, вернитесь к использованию какого-либо типа конечного автомата или тому подобного как можно быстрее. Регулярные выражения просто плохо масштабируются, чтобы использовать термин свободно. Они становятся сложными, трудными для интерпретации и даже неспособными.

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

1
10.12.2008 22:46:42
В одном случае здесь, я видел регулярное выражение на самом деле рекурсивный цикл с правильным вводом. Шипение серверных процессоров и позволило DOS иметь место. Излишне говорить, что я очень осторожен, когда вижу, что они подходят как решение по этой самой причине.
Steven Raybell 10.12.2008 22:57:31

Я думаю, что самый простой способ узнать, когда использовать регулярные выражения, а когда нет, - когда для поиска строк требуется оператор IF / THEN или что-либо, напоминающее ту или иную логику, тогда вам нужно что-то лучше простого сравнения строк, где регулярное выражение сияет

0
10.12.2008 22:55:14