Регулярное выражение для сопоставления комплекса «Где» для таблицы Certian - PullRequest
0 голосов
/ 01 мая 2018

У меня есть программа, которая принимает ограниченные предложения SQL Server WHERE и удаляет разделы, нацеленные на определенную таблицу. Примером такого предложения where является

AND (Util.Source = 'IP%' AND Util.ReqType = 'IP') AND (Util.Epinum имеет значение null) И ([Эпизод]. [YN] = 'Y')

Мне нужно вычеркнуть все части запроса, использующие таблицу Episode, и принять во внимание (, ) для включения операторов, а также квадратные скобки для имен полей и т. Д. Поэтому для этого у меня есть

private string BuildResourceWhereClauses(string whereClauses, string episodeTable)
{
    Regex r = new Regex(
        $"AND\\s+\\(*\\[*{episodeTable}\\]*\\.\\[*\\w+\\]*\\s*(=|<>|<=|>=)(\\s*\\'*(NULL|\\S+|\\((.*?)\\)+)\\'*\\s*\\)*){{1}}",
        RegexOptions.IgnoreCase);

    string tmp = r.Replace(whereClauses, String.Empty).Trim();
    return $" {tmp}";
}

Это хорошо работает, возвращаясь

AND (Util.Source = 'IP%' AND Util.ReqType = 'IP') AND (Util.Epinum имеет значение null)

Но теперь меня попросили расширить это, чтобы мы разрешили весь синтаксис предложения SQL WHERE. Так что теперь у нас может быть предложение where вроде

AND (Util.Source = 'IP%' AND Util.ReqType = 'IP') AND (Util.Epinum имеет значение null) И ([Episode]. [YN] = 'Y') AND (Episode.Paste = 'Y') И [Эпизод]. [Источник] = '% 6' И [Эпизод]. [TFC] NOT IN ('LWC', 'POD')

что мы должны "разобрать", поэтому я изменил вышеуказанный метод на

private string BuildResourceWhereClauses(string whereClauses, string episodeTable)
{
    Regex r = new Regex(
        $"AND\\s+\\(*\\[*{episodeTable}\\]*\\.\\[*\\w+\\]*\\s*(=|<>|<=|>=|LIKE|IN|NOT IN|IS|BETWEEN\\s+\\w+\\s+AND)(\\s*\\'*(NULL|\\S+|\\((.*?)\\)+)\\'*\\s*\\)*){{1}}",
        RegexOptions.IgnoreCase);

    string tmp = r.Replace(whereClauses, String.Empty).Trim();
    return $" {tmp}";
}

используя episodeTable = "Episode" Я получаю возвращено

AND (Util.Source = 'IP%' AND Util.ReqType = 'IP') AND (Util.Epinum равно нулю) 'POD')

Это пропущенные совпадения AND (Episode.Paste = 'Y'), AND [Episode].[Source] = '%6' и AND [Episode].[TFC] NOT IN ('LWC', 'POD').

  1. Что не так с регулярным выражением, как я могу изменить его, чтобы вернуть то, что я хочу?

  2. Вместо того, чтобы сделать это регулярное выражение более сложным, мы можем упростить его?

Спасибо за ваше время.


Ответ ниже удаляет некоторые функциональные возможности, которые у меня были раньше (моя ошибка в том, что я не указала, что мне нужно это сохранить! А также в том, что делает это настолько сложным - чтобы охватить все случаи "). Поэтому мне нужно сопоставить эту строку

AND (Util.Source = 'IP%' AND Util.ReqType = 'IP') AND (Util.Epinum имеет значение null) AND ([Episode]. [YN] = 'Y') и Episode.FRC между 10 и 20 и Episode.Dt между '2011/02/25' и '2011/02/27' AND (Util.Source = 'IP%' AND Util.ReqType = 'IP') AND (Util.Epinum имеет значение null) AND ([Эпизод]. [YN] = 'Y' И Episode.TFC НЕ НРАВИТСЯ '655r% «) И (Episode.Paste = 'Y') И [Эпизод]. [Источник] НЕ НРАВИТСЯ '% 6' И [Эпизод]. [TFC] НЕ ВХОДИТ ('LWC', 'POD') И [Эпизод]. [ TFC] NULL

Так что в C # мне нужен следующий код

string whereClaues = 
    "AND (Util.Source='IP%' AND Util.ReqType = 'IP') AND (Util.Epinum is null) " + 
    "AND ([Episode].[YN] = 'Y') AND Episode.FRC BETWEEN 10 AND 20 AND Episode.Dt between '2011/02/25' and '2011/02/27' " +
    "AND (Util.Source='IP%' AND Util.ReqType = 'IP') AND (Util.Epinum is null) AND ([Episode].[YN] = 'Y' AND Episode.TFC IS NOT LIKE '655r%') " +
    "AND (Episode.Paste = 'Y') AND [Episode].[Source] IS NOT LIKE '%6' AND [Episode].[TFC] NOT IN ('LWC', 'POD') AND [Episode].[TFC] IS NULL";
string tmp = r.Replace(whereClauses, String.Empty).Trim();

Чтобы дать tmp как

AND (Util.Source = 'IP%' AND Util.ReqType = 'IP') AND (Util.Epinum имеет значение null) AND (Util.Source = 'IP%' AND Util.ReqType = 'IP') AND (Util.Epinum равен нулю)

Удаление всех предложений Episode, включая операторы BETWEEN и операторы IS NOT NULL и IS NULL.

Есть

AND\s+\(*\[*Episode\]*\.\[*\w+\]*\s*(<>|[><]?=|(?:NOT\s+)?IN|(?:IS\s+)?LIKE|(?:IS\s+NOT\s+)?LIKE|BETWEEN(\s*\'*(\((.*?)\)+|NULL|\S+)\'*\s*\)*)AND)(\s*\'*(\((.*?)\)+|NULL|\S+)\'*\s*\)*)

Но это не соответствует

Episode.TFC IS NULL

1 Ответ

0 голосов
/ 01 мая 2018

Кажется, вы можете расширить свой шаблон следующим образом:

$@"AND\s+\(*\[*{episodeTable}\]*\.\[*\w+\]*\s*(<>|[><]?=|(?:NOT\s+)?IN)(\s*\'*(\((.*?)\)+|NULL|\S+)\'*\s*\)*)"

См. Демоверсию regex здесь .

Детали

  • AND - подстрока
  • \s+ - 1+ пробелов
  • \(* - 0+ ( символов
  • \[* - 0+ [ символов
  • Episode - название таблицы
  • \]* - 0+ ] символов
  • \. - . char
  • \[* - 0+ [ символов
  • \w+ - 1+ слово символов
  • \]* - 0+ ] символов
  • \s* - 0+ пробелов
  • (<>|[><]?=|(?:NOT\s+)?IN) - Группа 1: <>, <=, >=, =, NOT IN или IN
  • (\s*\'*(\((.*?)\)+|NULL|\S+)\'*\s*\)*) - Группа 2:
    • \s* - 0+ пробельных символов
    • \'* - 0+ ' символов
    • (\((.*?)\)+|NULL|\S+) - Группа 3:
      • \( - (
      • (.*?) - Группа 4: любые 0+ символов, кроме новой строки, как можно меньше
      • \)+ - 1+ ) символы
      • | - или
      • NULL - NULL подстрока
      • | - или
      • \S+ - 1+ непробельных символов
    • \'* - 0+ ' символов
    • \s* - 0+ пробелов
    • \)* - 0+ ) символов.
...