C # регулярное выражение не может найти текст с пробелами, если ввод экранирован - PullRequest
0 голосов
/ 23 мая 2019

Пытаясь найти немного текста с одним пробелом между двумя словами, я столкнулся с чем-то вроде ошибки. Я использую шаблон типа (abc)\s(abc), чтобы найти два конкретных слова. Теперь я экранирую свой ввод, используя Regex.Escape, но тогда мое регулярное выражение больше не совпадает, потому что пробелы экранируются (до \space), а затем не совпадают. Это предназначено?

Мой текст поступает от пользователя, поэтому, насколько я знаю, его следует экранировать.

Чтобы уточнить мой вопрос, следующий код:

Console.WriteLine("Original text: " + text);
Console.WriteLine("Escaped text: " + Regex.Escape(text));
Console.WriteLine("Matches non-escaped text: " + Regex.IsMatch(text, @"(abc)\s(abc)", RegexOptions.IgnoreCase));
Console.WriteLine("Matches escaped text: " + Regex.IsMatch(Regex.Escape(text), @"(abc)\s(abc)", RegexOptions.IgnoreCase));

Дает следующий результат для ввода abc abc

Оригинальный текст: abc abc

Экранированный текст: abc \ abc

Соответствует неэкранированному тексту: True

Соответствует экранированному тексту: False

В то время как я ожидал бы, что это все еще совпадет на пробелах

1 Ответ

1 голос
/ 23 мая 2019

Мой текст поступает от пользователя, поэтому, насколько я знаю, его следует экранировать.

Это ошибочная предпосылка.Если вы предполагаете это, то каждый раз, когда кто-то использует какое-либо из ваших приложений для создания записи для сотрудника с именем Shamus A. O'Leary, он, вероятно, в конечном итоге будет вставлен в БД как Shamus A\. O\'Leary, Shamus A. O'Leary, Shamus+A%2E+O'Leary и т. Д.в зависимости от того, откуда поступили данные и как вы решили, что их необходимо экранировать

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

Регулярно (abc)\s(abc) не соответствуетстрока abc\ abc из-за косой черты.Вы преобразовали свою строку из совпадения X во что-то еще (Y), а затем спросили синтаксический анализатор регулярных выражений, соответствует ли Y регулярному выражению.Это не более совпадение, чем abc+abc совпадение, исходя из предположения, что «когда URL-адреса экранированы, пробелы становятся плюсами, поэтому плюс и пробел должны означать одно и то же для регулярного выражения» - механизм регулярных выражений будет просто выглядетьв данных и скажите «плюс не символ пробела; нет совпадения».Движок регулярных выражений не будет смотреть на ваши данные и думать: «Эй, если я просто откажусь от этого, прежде чем запустить его через средство сопоставления с образцом ...», и он не будет смотреть на ваши данные и думать, что это «шаблон регулярного выражения» -выражение шаблона regex и данные, передаваемые в средство сравнения regex, работающее с этим шаблоном, - это очень разные вещи, и если вы хотите, чтобы ваши данные соответствовали описанному шаблону, не изменяйте данные после того, как вы определились с шаблоном

Таким образом, ошибка заключается в преобразовании строки с помощью замены символа (экранирования) до запроса соответствия

...