选择显示字体大小

db2中如何实现正则表达式(1)

正则表达式是什么?

正则表达式用于查找和替换字符串中的模式。正则表达式是用某种语法定义的,正则表达式引擎采用这种语法并将它与字符串进行比较。引擎返回字符串是否与语法匹配的指示;也即,该字符串是否包含能够从该语法派生的子串。此外,引擎还能够返回匹配的子串。术语“模式(pattern)”用来表示语法。

最基本的模式仅由单个字母组成。当与该模式进行比较时,包含这个字母的字符串就是一个“匹配”。例如,如果模式是“a”,则字符串“abcd”就是一个匹配,而字符串“xyz”则不是。正则表达式的强大功能来自于预定义的运算符(也称为元字符),它们可以用很小的空间来表示模式。根据“方言”和受支持的功能,可以使用不同的元字符。通常,其中的一些可用字符如下:

 — 二中择一[ ] — 分组* — 多次出现(也匹配零次出现)+ — 多次出现(至少一次)? — 随意的出现次数\\\\ — 反斜杠

不同的系统实现了常用正则表达式的各种扩展。编程语言 perl 中使用的正则表达式支持进一步的缩写。本文中所用的库实现了这些扩展。下面摘录了其中部分可以在 perl 正则表达式语言中使用的缩写:

\\s — 任意空白字符\\w — 任意字母数字字符\\d — 任意数字字符

另一个更高级的示例是模式“[a-z]* = ([0-9]0x00);”。与这个模式相匹配的字符串包含这样的子串:它由几个大写字母、后面跟上一个空格、一个等号、另一个空格,然后是一个数字或字符串“0x00”组成。该子串的最后一个字符必须是分号。使用 perl,这个模式可以表示为“\\w* = (\\d0x00);”。“nm = 0x00;”和“x = 7;”是两个可以与该模式匹配的字符串。但字符串“z = 123;”不能匹配,因为 123 是由三个数字所组成的。

db2 中的字符串匹配

除了 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">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">

尽管也可以用 sql 运算符表示模式“[a-z]* = ([0-9]0x00);”,但那样会很麻烦。例如,下列 select 语句的 where 子句中所使用的谓词会匹配字符串“str”中等号之后的部分,如 清单 1所示:

清单 1. 使用 like 匹配模式
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">

create table strtable ( c1 integer, str varchar(500) );insert into strtable values ( 1, 'some text;' ),                            ( 2, 'variable = 1234;' ),                            ( 3, 'var2 = ''string variable'';' ),                            ( 4, 'xyz = ' ),                            ( 5, 'myvar = 0x00;' ),                            ( 6, '# comment' ),                            ( 7, 'abc = def' );                            

这个 清单及其数据被用于下面的所有示例。

select * from strtable;c1          str----------- ------------------------------          1 some text;          2 variable = 1234;          3 var2 = 'string variable';          4 xyz =           5 myvar = 0x00;          6 # comment          7 abc = def  7 record(s) selected.

实现模式匹配函数

您可以使用 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">

select strfrom   strtablewhere regex1('\\w* = (\\d0x00);', str) = 1

在本示例中,使用带有 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">

create function regex1(pattern varchar(2048), string clob(10m))    returns integer    specific regexsimple    external name 'regexudf!regexpsimple'    language c    parameter style db2sql    deterministic    not fenced    returns null on null input    no sql    no external action    allow parallel;

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">

#include <pcre.h>#include <sqludf.h>void regexpsimple(    // input parameters    sqludf_varchar *pattern,      sqludf_clob *str,    // output    sqludf_integer *match,    // null indicators    sqludf_nullind *pattern_ind,  sqludf_nullind *str_ind,    sqludf_nullind *match_ind,    sqludf_trail_args){    pcre *re = null;    const char *error = null;    int erroffset = 0;    int rc = 0;    // we assume successful return    *match_ind = 0;    // compile the pattern to its internal representation    re = pcre_compile(pattern, 0 /* default options */, &error,        &erroffset, null);    if (re == null) {        snprintf(sqludf_msgtx, 70, "regexp compilation failed at "            "offset %d: %s\\n", erroffset, error);        strcpy(sqludf_state, "38900");        (*pcre_free)(re);        return;    }    // match the string againts the pattern    rc = pcre_exec(re, null, str->data, str->length, 0,            0 /* default options */, null, 0);    switch (rc) {      case pcre_error_nomatch:        *match = 0;        break;      case pcre_error_badoption:        snprintf(sqludf_msgtx, 70, "an unrecognized bit was set in the "            "options argument");        strcpy(sqludf_state, "38901");        break;      case pcre_error_nomemory:        snprintf(sqludf_msgtx, 70, "not enough memory available.");        strcpy(sqludf_state, "38902");        break;      default:        if (rc < 0) {            snprintf(sqludf_msgtx, 70, "a regexp match error "                "occured: %d", rc);            strcpy(sqludf_state, "38903");        }        else {            *match = 1;        }        break;    }    // cleanup    (*pcre_free)(re);    return;}

用法示例

下列查询试图从表 strtable 中找出包含注释文本的所有字符串。注释以“#”开头,所以模式是“#”后跟非空文本。

select c1, strfrom   strtablewhere  regex1('#\\s*\\w+', str) = 1;

结果只包含 c1 = 6 的行。

c1          str----------- -------------------------          6 # comment;  1 record(s) selected.

在第二个示例中,我们试图找到这种赋值形式的字符串;即“text = text”。为了进一步缩小范围,我们只查找那些右端为数值的赋值。将十六进制表示法作为有效数值对待。

select c1, strfrom   strtablewhere  regex1('\\w+\\s*=\\s*(\\d+0x\\d\\d)', str) = 1;

除了 c1 为 2 或 5 的两行以外,其它行都不包含数值的赋值,因此不会出现在结果中:

c1          str----------- -------------------------          2 variable = 1234;          5 myvar = 0x00;  2 record(s) selected.  




  


 


关键字 本文所属关键字

相关 与本文相关文章

分类 所有文章关键字导航

源码编程相关

Java   Asp   PHP   .Net   XML   C/C++   CGI   VB   Jsp   J2ee   J2se   J2me   EJB   Servlet   Tomcat   Resin   Struts   Weblogic   Eclipse   ANT   GUI   JMS   Web servise   IDEA   Webphere   Hibernate   Spring   Jboss   Applet   Swing   Socket   Javamail   Perl   Ajax   P2P   安全   模式   框架   测试   开源   游戏

SQL数据库相关

My-SQL   Ms-SQL   Access   DB2   Oracle   Sybase   SQLserver   索引   存储过程   加密   数据库   分页   视图  

手机无线相关

3G   Wap   CDMA   GRPS   GSM   IVR   彩信   短信   无线   增值业务

网页设计制作相关

HTML   CSS   网页配色   网页特效   Javascript   VBscript   Dreamweaver   Frontpage   JS   Web   网站设计

网站建设推广相关

建站经验   网站优化   网站排名   推广   Alexa

操作系统/服务器相关

Windows XP   Windows 2000   Windows 2003   Windows Me   Windows 9.x   Linux   UNIX   注册表   操作系统   服务器   应用服务器

图形图像多媒体相关

Photoshop   Fireworks   Flash   Coreldraw   Illustrator   Freehand   Photoimpact   多媒体   图形图像

标准 网站致力的规范

Valid CSS!

无不良内容,无不良广告,无恶意代码

Valid XHTML 1.0 Transitional

creativecommons