0

我有一个日志条目,我只想用正则表达式提取 SQL 语句。SQL 语句可以是任何 DDL 或 DML 语句,并且可能有几行。参数部分可能会丢失,并且“在 xx 记号中获得 xx 结果”也可能会丢失。但是 ":SQLEnd:" 行总是存在的。这里有些例子

SELECT col1, col2 FROM table WHERE col1 = :id and col2= :num ORDER BY ORDERID ASC

Params:
:id -> 60081
:num-> 1

Got 2 Results in 0 Ticks
:SQLEnd:

或者:

SELECT col1, col2 FROM table WHERE col1 = :id and col2= :num ORDER BY ORDERID ASC

Got 2 Results in 0 Ticks
:SQLEnd:

或者:

SELECT col1, col2 FROM table WHERE col1 = :id and col2= :num ORDER BY ORDERID ASC

Params:
:id -> 60081
:num-> 1

:SQLEnd:

或者:

SELECT col1, col2 FROM table WHERE col1 = :id and col2= :num ORDER BY ORDERID ASC

:SQLEnd:
4

2 回答 2

0

与您的示例相匹配的基本正则表达式是:

SELECT .+?:SQLEnd:

您需要确保.将匹配换行符。在 PHP 中,这将是:

/SELECT .+?:SQLEnd:/s

但是,这个正则表达式不是很健壮,因为它在与某些 SQL 查询(例如:包含一个或多个子查询的SELECT查询)一起使用时可能会中断。并且您想匹配“任何 DDL 或 DML 语句”,这对于正则表达式来说非常复杂。正如马克所说,使用解析器而不是正则表达式会更好。

编辑

在 C#.net 中,您将使用:

new Regex("SELECT .+?:SQLEnd:", RegexOptions.Singleline);

的文档RegexOptions.Singleline这里

指定单行模式。更改点 (.) 的含义,使其匹配每个字符(而不是除 \n 之外的每个字符)。

您还可以使用此内联选项来启用单行模式:

new Regex("(?s)SELECT .+?:SQLEnd:");
于 2012-11-28T17:42:22.907 回答
0

正如 Mark Thalman 在评论中提到的,您可能希望为此研究一个好的解析器,有多种可用的语言可以涵盖您应该使用的任何语言。

http://code.google.com/p/python-sqlparse/(例如)是 Python SQL 解析器的一个很好的例子

要回答您的问题,我将使用正则表达式:

'(s?)(m?)(.*?^:SQLEnd:)'

这将匹配任何 DDL/DML 语句,但它会粗略地匹配(解释如下)。

开头的标志表示 DOTALL(点包含所有字符)和 MULTILINE($ 和 ^ 表示行的结尾和开头)。大多数语言都有内置的标志,您可以使用它们实现的任何正则表达式类来激活这些标志。(即 Pythonre.DOTALLre.MULTILINE来自import re.

请注意,这个正则表达式只会获取 ":SQLEnd:" 实例之间的表达式 - 所以

SELECT col1, col2 FROM table WHERE col1 = :id and col2= :num ORDER BY ORDERID ASC

Params:
:id -> 60081
:num-> 1

Got 2 Results in 0 Ticks
:SQLEnd:

将是一组并且

or:

SELECT col1, col2 FROM table WHERE col1 = :id and col2= :num ORDER BY ORDERID ASC

Got 2 Results in 0 Ticks
:SQLEnd:

将是另一个。这是粗略的(但我能想到的唯一方法可以轻松解释任何 DDL/DML 语句)但希望对您有用。如果这不是一个选项,我强烈推荐使用 SQL 解析器。

于 2012-11-28T17:58:53.797 回答