Удаление псевдонимов из оператора выбора SQL с использованием C # и регулярных выражений - PullRequest
1 голос
/ 09 июля 2010

Я изучаю регулярные выражения и немного с ними играю. Я предложил себе упражнение, в котором у меня есть метод, который удаляет псевдонимы столбцов в операторе SQL Select. Это должно работать так:

  • Метод может удалить псевдонимы в SQL выберите оператор с ключевым словом AS: «Выберите столбец A КАК A»
  • Метод может удалить псевдонимы в SQL выберите заявление без AS Ключевое слово: «Выбрать столбец B»
  • Метод может удалить псевдонимы в SQL выберите заявление, которое содержит «Символы операции» (например, символ операции конкатенации): «Выберите« Привет »|| «Мир!» КАК HelloWorld»

До сих пор я создал два метода, которые работают только в определенных случаях. В следующем коде приводится сводная информация о том, что я сделал, и о проблемах, с которыми я сталкиваюсь.

static void Main(string[] args)
{
    string cols1 = "ColA as AliasA, ColB   AliasB  , As As ASasas, Asasasas as As";
    string cols2 = "'aaa' || 'bbb'  AS   AliasC , 'ccc' || 'ddd' AliasD";

    string answer1 = RemAliases(cols1);     // Works fine
    string answer2 = RemAliases2(cols2);    // Works fine
    string answer3 = RemAliases2(cols1);    // Doesn't work
    string answer4 = RemAliases(cols2);     // Doesn't work            
}

static string RemAliases2(string inputSql)
{
    string pattern1 = @"(.+)\s+AS\s+\w+";
    string replacement1 = "$1";
    string pattern2 = @"(.+)\s+\w+";
    string replacement2 = "$1";
    string result = Regex.Replace(inputSql, pattern1, replacement1, RegexOptions.IgnoreCase);
    result = Regex.Replace(result, pattern2, replacement2, RegexOptions.IgnoreCase);
    return result;
}

static string RemAliases(string inputSql)
{
    string pattern1 = @"(\w+)\s+AS\s+\w+";
    string replacement1 = "$1";
    string pattern2 = @"(\w+)\s+\w+";
    string replacement2 = "$1";
    string result = Regex.Replace(inputSql, pattern1, replacement1, RegexOptions.IgnoreCase);
    result = Regex.Replace(result, pattern2, replacement2, RegexOptions.IgnoreCase);
    return result;
}

Я не ожидал, что «RemAliases ()» будет работать нормально с «cols2», поскольку «\ w +» не соответствует символу «|». Хотя я ожидал, что «RemAliases2 ()» также будет хорошо работать с «cols1». Может ли кто-нибудь оказать мне некоторую помощь, чтобы узнать, почему «RemAliases2 ()» не работает в случае с «cols1»? Пожалуйста, не стесняйтесь давать любые другие советы о том, как я использовал эти регулярные выражения.

Заранее спасибо.

PS: я использую .NET 2.0

Ответы [ 3 ]

0 голосов
/ 09 июля 2010

Что касается того, почему RemAliases2 не работает для ваших cols1, так это то, что. + Является жадным - требуется столько, сколько может.

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

(.+) --> "ColA as AliasA, ColB   AliasB  , As As ASasas, Asasasas"
\s+  --> " "
AS   --> "as"
\s+  --> " "
\w+  --> "As"

Где я разбил каждую часть регулярного выражения на отдельные строки и показал часть вашей строки, которая соответствует "" после "->.

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

Один из возможных лучших стартов (для конкретного случая) будет:

(.+?)(\s+as\s+\w+\s*)(,|$)

Я изменил +, чтобы он был не жадным (+?), Я добавил опцию пробела после имени столбца псевдонима, но перед запятой (\ s *), и добавил чередующуюся запятую с концом строки, чтобы правильно завершить выражение (, | $), чтобы вы могли повторяться несколько раз для каждого поля в предложении select.

Однако, это соответствует только одному совпадению, а не нескольким (обратите внимание, что я знаю регулярные выражения, но не C #, поэтому я не могу точно сказать, как это работает в C #, но концепции довольно общие). Либо вам нужно многократно повторять строку, либо вызывать функцию с глобальным флагом. (В Java вы бы сделали это, вызвав replaceAll () вместо replace () - я предполагаю, что C # имеет аналогичную конструкцию.)

При глобальном применении и вставке $ 1 и $ 3 в заменяющую строку получится измененное cols1:

ColA, ColB AliasB, As, Asasasas

Тогда у вас есть кейс без AS, который сложнее!

0 голосов
/ 10 июля 2010

Для того, чтобы ваше регулярное выражение работало надежно, вам нужно быть гораздо более усердным в определении того, чему оно должно соответствовать, а не пытаться использовать ярлык с .+.Приведенное ниже объяснение довольно многословно.Это мыслительный процесс, который я использовал при построении регулярного выражения.

На основании ваших примеров у вас либо есть идентификатор, например colA, либо конкатенация строк в одинарных кавычках, например 'aaa' || 'bbb'.Вы можете сопоставить идентификатор с \w+ и строки с '[^']*'(?:\s*\|\|\s*'[^']*')*.Мое регулярное выражение для строк позволяет объединять любое их число, включая отсутствие конкатенации (т. Е. Только одну строку в одинарных кавычках).

Чтобы сопоставить любую из этих двух, мы можем использовать \b\w+\s+|'[^']*'(?:\s*\|\|\s*'[^']*')*\s*.Я добавил \s+ после идентификатора, потому что он должен быть отделен от следующего пробелом.Для объединенных строк \s* делает разделительные пробелы необязательными.

За идентификатором или строками необязательно может следовать ключевое слово As.Если ключевое слово присутствует, должен следовать пробел.Мы можем закодировать это как (As\s+)?.

Наконец, за всем этим следует другой идентификатор.Это легко сопоставить с \w+.

Собрав все это вместе, мы получим следующее регулярное выражение:

(\b\w+\s+|'[^']*'(?:\s*\|\|\s*'[^']*')*\s*)(As\s+)?\w+

Я поместил группу захвата вокруг первой части.Нам это понадобится для поиска и замены.Замена этого регулярного выражения только именем столбца или конкатенацией строк эффективно удаляет часть «как».Текст замены просто $1.

или в C #:

result = Regex.Replace(inputSql, 
    @"(\b\w+\s+|'[^']*'(?:\s*\|\|\s*'[^']*')*\s*)(As\s+)?\w+", "$1",
    RegexOptions.IgnoreCase);
0 голосов
/ 09 июля 2010

Одна проблема с (.+)\s+AS\s+\w+ состоит в том, что (.+) является жадным.Это означает, что он будет продолжать работать до тех пор, пока не совпадет с другими символами, что означает новую строку.Если вы положите?после + это сделает его ленивым, поэтому он остановится, как только найдет первый пробел, потому что пробел соответствует \ s.

Следующая проблема заключается в том, что.также соответствует пустому пространству.Таким образом, когда у вас есть случай ColB AliasB ,, он продолжает работать, пока не получит «AS» для соответствия следующей части регулярного выражения.В этом случае это входит в следующую группу.Итак, вам действительно лучше использовать \ w +, как вы делали в функции RemAliases.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...