Я стараюсь быть кратким и лаконичным. Мне нужно написать программу, которая принимает запросы в форме SQL и выполняет поиск в XML. Прямо сейчас я пытаюсь разобрать строку на логические части, чтобы с ними можно было работать. У меня есть строка в качестве входных данных, и я хочу получить MatchCollection в качестве выходных данных.
Обратите внимание, что приведенная ниже тестовая строка имеет особый формат, который я навязываю пользователю для простоты. Разрешен только один оператор в строке, вложенные запросы исключены -
string testString = "выберите яблоки \ n из dblp \ r, где мы съели \ n сгруппировать по всем \ r БЕЗ СТЫДА \ n";
Я использую Regex со следующим шаблоном:
Regex reg = new Regex(@"(?<select> \A\bselect\b .)" +
@"(?<from> ^\bfrom\b .)" +
@"(?<where> ^\bwhere\b .)" +
@"(?<groupBy> ^\bgroup by\b .)" +
@"(?<having> ^\bhaving\b .)"
, RegexOptions.IgnoreCase | RegexOptions.Multiline
);
Насколько я знаю, это должно дать мне совпадения для каждой группы с тестовой строкой. Я бы искал точное совпадение "select" в начале каждой строки, за которым следовали любые символы, кроме символов новой строки.
Теперь создаю коллекцию:
MatchCollection matches = reg.Matches(testString);
Чтобы убедиться, что это работает, я использовал foreach и распечатал такие совпадения, как:
foreach(Match match in matches)
{
Console.WriteLine("Select: {0}", match.Groups["select"]);
//and so on
}
Проблема в том, что коллекция всегда пуста. Где-то в регулярном выражении должен быть недостаток, но я слишком неопытен, чтобы его найти. Не могли бы вы мне помочь? Большое спасибо вам!
Я пробовал использовать. * Вместо просто. пока мне не сказали это. даже вычислил бы несколько символов. Не сомневаюсь, что это может быть проблемой, но даже при замене я не получаю результата.
Я не понимаю, почему так сложно сопоставить строку, начинающуюся с определенного слова, и добавить к ней какие-либо символы, пока регулярное выражение не найдет новую строку. Мне кажется, что это должна быть относительно простая задача.





Я думаю, вам нужно явно сопоставить терминаторы строки, а также лучше обрабатывать пробелы, как предлагали другие. Предполагая, что пользователь может выбирать между \ r и \ n, попробуйте
@"(?<select>\Aselect .+)[\n\r]" +
@"(?<from>\s*from .+)[\n\r]" +
@"(?<where>\s*where .+)[\n\r]" +
@"(?<groupBy>\s*group by .+)[\n\r]" +
@"(?<having>\s*having .+)[\n\r]"
Пока вы используете регулярные выражения, вы, вероятно, захотите сделать немного лучше:
@"\Aselect (?<select>.+)[\n\r]" +
@"\s*from (?<from>.+)[\n\r]" +
@"\s*where (?<where>.+)[\n\r]" +
@"\s*group by (?<groupBy>.+)[\n\r]" +
@"\s*having (?<having>.+)[\n\r]"
Моя самая большая проблема с регулярными выражениями для такого рода использования заключается в том, что единственное сообщение об ошибке, которое вы можете дать, - это то, что что-то не удалось. Вы не можете предоставить пользователю дополнительную информацию о том, что он сделал не так.
Может возникнуть проблема с сопоставлением новой строки: это LF (стандарт Unix), CR (MacOS) или CR LF (Windows)? Если вы не знаете, возможно, вам следует сопоставить его с: [\n\r]+
редактировать: вы включили в тестовую строку некоторые пробелы, окружающие символы новой строки, которые вы не учитываете в своем rexex.
(?<from>^\s*from\b.*[\n\r]+$)
Как вы сказали, достаточно легко сопоставить ключевое слово (а), а затем использовать (. +), Чтобы сопоставить остальную часть строки. Но вы должны сопоставить всех промежуточных персонажей, а вы этого не делаете. (Якорь строки ^ соответствует позиция следующая - разделителю строк, а не самому разделителю.) Вы можете использовать \ s + для использования разделителя строк, а также любых ведущих пробелов в следующей строке.
@"select\s+(?<select>.+)\s+" +
@"from\s+(?<from>.+)\s+" +
@"where\s+(?<where>.+)\s+" +
@"group by\s+(?<groupBy>.+)\s+" +
@"having\s+(?<having>.+)";
Я также изменил порядок вещей, чтобы ключевые слова SQL не записывались; это кажется излишним, поскольку вы используете именованные группы.
Я не пытался создать для вас рабочее регулярное выражение, но вижу несколько проблем. Другие указали на первые две проблемы, но не на третью.