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

И (Util.Source = 'IP%' И Util.ReqType = 'IP') И (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}";
}

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

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

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

И (Util.Source = 'IP%' И Util.ReqType = 'IP') И (Util.Epinum имеет значение null) И ([Эпизод]. [YN] = 'Y') И (Episode.Paste = 'Y' ) И [Эпизод]. [Источник] = '% 6' И [Эпизод]. [TFC] НЕ ВХОДИТ ('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" меня вернули

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

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

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

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

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


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

И (Util.Source = 'IP%' AND Util.ReqType = 'IP') И (Util.Epinum имеет значение null) И ([Episode]. [YN] = 'Y') AND 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 ([Episode ]. [YN] = 'Y' И Episode.TFC НЕ КАК '655r%') И (Episode.Paste = 'Y') И [Episode]. [Source] НЕ ПОДОБНЫЙ '% 6' И [Episode] . [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 как

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

Удаление всех предложений 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 ЕСТЬ NULL

1
MoonKnight 1 Май 2018 в 16:29

1 ответ

Лучший ответ

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

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

См. демонстрацию регулярных выражений здесь.

Подробности

  • AND - подстрока
  • \s+ - 1+ пробелов
  • \(* - 0+ ( символов
  • \[* - 0+ [ символов
  • Episode - имя таблицы
  • \]* - 0+ ] символов
  • \. - символ .
  • \[* - 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+ ) символов.
1
Wiktor Stribiżew 1 Май 2018 в 14:27