正则表达式是什么? 最基本的模式仅由单个字母组成。当与该模式进行比较时,包含这个字母的字符串就是一个“匹配”。例如,如果模式是“a”,则字符串“abcd”就是一个匹配,而字符串“xyz”则不是。正则表达式的强大功能来自于预定义的运算符(也称为元字符),它们可以用很小的空间来表示模式。根据“方言”和受支持的功能,可以使用不同的元字符。通常,其中的一些可用字符如下: 不同的系统实现了常用正则表达式的各种扩展。编程语言 perl 中使用的正则表达式支持进一步的缩写。本文中所用的库实现了这些扩展。下面摘录了其中部分可以在 perl 正则表达式语言中使用的缩写: 另一个更高级的示例是模式“[a-z]* = ([0-9]0x00);”。与这个模式相匹配的字符串包含这样的子串:它由几个大写字母、后面跟上一个空格、一个等号、另一个空格,然后是一个数字或字符串“0x00”组成。该子串的最后一个字符必须是分号。使用 perl,这个模式可以表示为“\\w* = (\\d0x00);”。“nm = 0x00;”和“x = 7;”是两个可以与该模式匹配的字符串。但字符串“z = 123;”不能匹配,因为 123 是由三个数字所组成的。 db2 中的字符串匹配 xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance">= 或 <> 谓词:逐字符地比较两个字符串是否相等。 尽管也可以用 sql 运算符表示模式“[a-z]* = ([0-9]0x00);”,但那样会很麻烦。例如,下列 select 语句的 where 子句中所使用的谓词会匹配字符串“str”中等号之后的部分,如 清单 1所示: 清单 1. 使用 like 匹配模式
正则表达式用于查找和替换字符串中的模式。正则表达式是用某种语法定义的,正则表达式引擎采用这种语法并将它与字符串进行比较。引擎返回字符串是否与语法匹配的指示;也即,该字符串是否包含能够从该语法派生的子串。此外,引擎还能够返回匹配的子串。术语“模式(pattern)”用来表示语法。 — 二中择一[ ] — 分组* — 多次出现(也匹配零次出现)+ — 多次出现(至少一次)? — 随意的出现次数\\\\ — 反斜杠\\s — 任意空白字符\\w — 任意字母数字字符\\d — 任意数字字符
除了 extender 以外,db2 还允许几种用于文本比较的函数和运算符。但那些函数和运算符要么在用于模式匹配的功能方面有限制,要么就是会给可能使用它们的查询带来复杂性。这里简要地摘录几个可用的功能:
xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance">xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance">like 谓词:使用通配符的基本模式匹配。
xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance">xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance">locate 函数:在字符串中查找子串。
xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance">
xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance">select strfrom strtablewhere ( str like '% = 0;%' or str like '% = 1;%' or str like '% = 2;%' or str like '% = 3;%' or str like '% = 4;%' or str like '% = 5;%' or str like '% = 7;%' or str like '% = 7;%' or str like '% = 8;%' or str like '% = 9;%' or str like '% = 0x00;%' )
这增加了可以匹配“[a-z]*”子模式的谓词的复杂度,这可以使用对整个字符串进行迭代并进行逐字符比较的函数来完成,但您会发现使用内置功能既冗长又复杂。
示例方案
让我们定义下列清单( 清单 2)并插入几行:
清单 2. 创建我们的样本表
xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance">
|
这个 清单及其数据被用于下面的所有示例。
|
实现模式匹配函数
您可以使用 db2 的可扩展机制,在 sql 语句内使用 udf,以便显著地改善这种情形。通过定义名为 regex1 的 udf(它采用模式和字符串作为输入参数), 清单 1中的 where 子句现在可以写得象 清单 3中所示的那样:
清单 3. 使用 regex udf 来简化模式匹配
xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance">
|
在本示例中,使用带有 perl 扩展的正则表达式来匹配完整的模式,而不仅仅是 清单 1中给出的 like 谓词所对应的部分模式。正如您所看到的,使用函数来为该模式编写谓词比用 like 谓词表示同样的语义要容易得多。
实现 udf
在我的示例实现中,我选择了现有的名为 pcre(perl 兼容的正则表达式,perl-compatible regular expression)的模式匹配引擎。该引擎提供了用来处理模式和执行匹配的 c api。该引擎和查询中所用的 sql 语言之间“缺失的部分”是 udf。该 udf 由两部分组成:
清单 4显示了用于创建该函数的 sql 语句。
清单 4. 注册 regex1 函数
xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance">
|
xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance">注:请参阅 xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance">db2 sql reference以获取所有子句的详细含义。可以修改参数的长度以适应您的需求。我在此处展示某些值并没有任何推荐使用它们的用意。
第二部分由一小段 c 代码组成,它实现了 udf 入口点。在查询执行期间,db2 为每个要与模式匹配的行调用这个入口点。 清单 5中的示例列出了该代码的清单。有关 pcre_* 函数和宏的描述,请参考 pcre 库的文档。有关 c 代码的编译和共享库的构建,请参考 xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance">db2 application development guide。
清单 5. 实现 rege1x udf 入口点的 c 代码
xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance">
|
用法示例
下列查询试图从表 strtable 中找出包含注释文本的所有字符串。注释以“#”开头,所以模式是“#”后跟非空文本。
|
结果只包含 c1 = 6 的行。
|
在第二个示例中,我们试图找到这种赋值形式的字符串;即“text = text”。为了进一步缩小范围,我们只查找那些右端为数值的赋值。将十六进制表示法作为有效数值对待。
|
除了 c1 为 2 或 5 的两行以外,其它行都不包含数值的赋值,因此不会出现在结果中:
|