《DB2中实现正则表达式》由会员分享,可在线阅读,更多相关《DB2中实现正则表达式(17页珍藏版)》请在金锄头文库上搜索。
1、DB2 中实现正则表达式(1)http:/ 2005-12-01 10:00 出处:IBM 中国 【导读】本文简略地介绍了正则表达式以及 DB2 中可用的字符串比较和匹配功能。还描述了为什么正则表达式的强大功能是如此有用。 正则表达式正则表达式用于查找和替换字符串中的模式。正则表达式是用某种语法定义的,正则表达式引擎采用这种语法并将它与字符串进行比较。引擎返回字符串是否与语法匹配的指示;也即,该字符串是否包含能够从该语法派生的子串。此外,引擎还能够返回匹配的子串。术语“模式(pattern) ”用来表示语法。 最基本的模式仅由单个字母组成。当与该模式进行比较时,包含这个字母的字符串就是一个“匹
2、配” 。例如,如果模式是“a” ,则字符串“abcd”就是一个匹配,而字符串 “xyz”则不是。正则表达式的强大功能来自于预定义的运算符(也称为元字符) ,它们可以用很小的空间来表示模式。根据“方言”和受支持的功能,可以使用不同的元字符。通常,其中的一些可用字符如下:| 二中择一 分组* 多次出现(也匹配零次出现)+ 多次出现(至少一次)? 随意的出现次数 反斜杠 不同的系统实现了常用正则表达式的各种扩展。编程语言 Perl 中使用的正则表达式支持进一步的缩写。本文中所用的库实现了这些扩展。下面摘录了其中部分可以在 Perl 正则表达式语言中使用的缩写:s 任意空白字符w 任意字母数字字符d
3、任意数字字符 另一个更高级的示例是模式“A-Z* = (0-9|0x00);”。与这个模式相匹配的字符串包含这样的子串:它由几个大写字母、后面跟上一个空格、一个等号、另一个空格,然后是一个数字或字符串“0x00”组成。该子串的最后一个字符必须是分号。使用 Perl,这个模式可以表示为“w* = (d|0x00);”。 “NM = 0x00;”和“X = 7;”是两个可以与该模式匹配的字符串。但字符串“Z = 123;”不能匹配,因为 123 是由三个数字所组成的。DB2 中的字符串匹配除了 Extender 以外,DB2 还允许几种用于文本比较的函数和运算符。但那些函数和运算符要么在用于模式匹
4、配的功能方面有限制,要么就是会给可能使用它们的查询带来复杂性。这里简要地摘录几个可用的功能:= 或 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;cas
5、e PCRE_ERROR_NOMEMORY:snprintf(SQLUDF_MSGTX, 70, Not enough memory available.);strcpy(SQLUDF_STATE, 38902);break;default:if (rc data;*match_ind = 0;switch (SQLUDF_CALLT) case SQLUDF_FIRST_CALL:/ initialize data on the scratchpad scratch-re = NULL;scratch-extra = NULL;scratch-error = NULL;scratch-err
6、Offset = 0;/ compile the pattern (only in the FIRST callscratch-re = pcre_compile(pattern, 0 /* default options */,&scratch-error, &scratch-errOffset, NULL);if (scratch-re = NULL) snprintf(SQLUDF_MSGTX, 70, Regexp compilation failed at offset %d: %sn, scratch-errOffset, scratch-error);strcpy(SQLUDF_
7、STATE, 38900);rc = -1;break;/ further analyze the pattern (might return NULL)scratch-extra = pcre_study(scratch-re,0 /* default options */, &scratch-error);/* fall through to NORMAL call because DB2 expects a resultalready in the FIRST call */case SQLUDF_NORMAL_CALL:/ match the current stringrc = pc
8、re_exec(scratch-re, scratch-extra, str-data,str-length, 0, 0 /* default options */, NULL, 0);switch (rc) case PCRE_ERROR_NOMATCH:*match = 0;rc = 0;break;case PCRE_ERROR_BADOPTION:snprintf(SQLUDF_MSGTX, 70, An unrecognized bit was set in the options argument);strcpy(SQLUDF_STATE, 38901);rc = -1;break
9、;case PCRE_ERROR_NOMEMORY:snprintf(SQLUDF_MSGTX, 70, Not enough memory available.);strcpy(SQLUDF_STATE, 38902);rc = -1;break;default: if (rc re);(*pcre_free)(scratch-extra);return; 为了进一步改进该函数的性能,我添加了对函数 pcre_study() 的调用,该函数是由模式匹配引擎提供的。该函数进一步分析了该模式,并将额外的信息存储在独立的结构中。然后,在实际的匹配期间使用这些额外的信息来加快处理速度。通过使用一个非
10、常简单的模式和大约 4000 行的表,我获得了 5% 的执行时间的改善。当然,模式越复杂,差异将越显著。DB2 中实现正则表达式(3) http:/ 2005-12-01 10:00 出处:IBM 中国 【导读】本文简略地介绍了正则表达式以及 DB2 中可用的字符串比较和匹配功能。还描述了为什么正则表达式的强大功能是如此有用。 先前提到该实现假定模式在处理期间不会随行的不同而更改。当然,如果模式确实更改了,您可以进行少量的改写以再次编译一个模式。要这样做,有必要跟踪当前(已编译的)模式并在每次调用中将它与所提供的模式进行比较。也可以在高速暂存中维护当前模式。但必须将它复制到独立的缓冲区,并且不
11、能通过指针模式直接引用它,因为这个指针或它所引用的数据可能会更改或变为无效。至于相应的代码更改,就当作练习留给读者了。返回匹配子串大多数模式匹配引擎提供了一种方法,返回与指定模式或其一部分相匹配的子串。如果想在 SQL 中使用这种能力,则必须使用不同的方法来实现匹配函数。给定的字符串可能包含不止一个匹配的子串。例如,当解析类似“abc = 123;”或“def = some text;”这样的字符串时,用户可能会希望检索由等号分隔的两个子串。您可以使用模式“w+s*=s*(d+|ws *);”来表示适用于该字符串的语法规则。Perl 兼容的正则表达式允许您捕获等号两边的子串。最后,必须将要捕获
12、的子串用括号括起来。我已经用该方式编写了第二个子串,但第一个子串不是这样编写的。用于该用途的最终模式是这样的:(w+)s*=s*(d+|ws*);当把这个模式应用于字符串“abc= 123;”或“def = some text;”时, “abc”或“def”分别与“(w+)”匹配,空格和等号是通过“s*=s*”查找的,并用另外的“(d+| ws*)”涵盖了余下的子串。在“(d+|ws*)”中,第一个选项与任何至少由一个数字“d+ ”组成的数匹配,而第二个选项解析任何由字母和空格组成的由单引号括起的字符串“ws*”。在 DB2 中做到这一点的需求可以描述成:为一次 UDF 调用返回多个结果。换句
13、话说,就是返回针对模式进行匹配的单个字符串的多个子串。DB2 的表函数是完成这一任务的完美工具。实现表 UDF和以前一样,必须在数据库中创建该函数。 清单 8 中的下列语句正是用于这一任务的: 清单 8. 注册名为 regex3 的表 UDF CREATE FUNCTION regex3(pattern VARCHAR(2048), string CLOB(10M)RETURNS TABLE ( position INTEGER, substring VARCHAR(2048) )SPECIFIC regexSubstrEXTERNAL NAME regexUdf!regexpSubstrLA
14、NGUAGE CPARAMETER STYLE DB2SQLDETERMINISTICNOT FENCEDRETURNS NULL ON NULL INPUTNO SQLNO EXTERNAL ACTION SCRATCHPAD 50NO FINAL CALLDISALLOW PARALLEL; 实现该函数的实际逻辑的 C 代码与 清单 7 中的代码非常相似,但根据表函数所必须满足的特殊需求对它进行了改编,如 清单 9 所示。DB2 中实现正则表达式(4) http:/ 2005-12-01 10:00 出处:IBM 中国 【导读】本文简略地介绍了正则表达式以及 DB2 中可用的字符串比较和匹
15、配功能。还描述了为什么正则表达式的强大功能是如此有用。 清单 9. 实现表函数将要使用的 regex3 函数 #include #include #include #include struct scratchPadMapping pcre *re;pcre_extra *extra;const char *error;int errOffset;int numSubstr;int *substr;int currentSubstr;void regexpSubstr(/ input parametersSQLUDF_VARCHAR *pattern, SQLUDF_CLOB *str,/ outputSQLUDF_INTEGER *pos, SQLUDF_VARCHAR *substr,/ null indicatorsSQLUDF_NULLIND *pattern_ind, SQLUDF_NULLIND *str_ind,SQLUDF_NULLIND *pos_ind, SQLUDF_NULLIND *substr_ind,SQLUDF_TRAIL_ARGS_ALL) / SQLUDF_