如何利用正则表达式排除字符串给指定字符串加长?

查看: 6112|回复: 19
用正则表达式,如何从字符串中提取特定符号前的数字?
阅读权限20
在线时间 小时
用正则表达式,如何从字符串中提取特定符号前的数字?如:
YJV-5*16& && && && && & '提取*前的数字5
YJV22-5*16
.Pattern=[]'此部分怎么写?
阅读权限50
在线时间 小时
请看该贴四楼的代码是否符合你的要求?
阅读权限20
在线时间 小时
好象不行!!!![em01]
阅读权限95
在线时间 小时
针对本例,可能不用正则更快。
& && &'撰写:老朽
& && &'网址:
& && &'日期: 下午 08:11:08
Sub zldccmx()
& & Dim RegEx As New RegExp
& & Set RegEx = CreateObject(&VBSCRIPT.REGEXP&)& & 'RegEx为建立正则表达式
& & RegEx.Global = True & & '设置全局可用
& & arr = Array(&YJV-5*16&, &YJV22-5*16&, &VV-5*16&, &V22-5*16&, &BV-2*2.5&, &BV-3*2.5&, &BVV-2*2.5&, &BVV-3*2.5&)
& & For i = 0 To UBound (arr)
& & RegEx.Pattern = &-\S*\*& '取 - 与 *之间的部分
& & For Each b In RegEx.Execute(arr(i)) '取返回结果
& && &&&RegEx.Pattern = &-|\*& '去除 - 和 *
& && &&&arr(i) = RegEx.Replace(b, &&)
& & MsgBox Join(arr, vbLf)
阅读权限95
在线时间 小时
说实话,对正规也是在学习中
阅读权限20
在线时间 小时
谢谢老朽,如表格中的行是不断增加的,又如何改这个
20:54 上传
点击文件名下载附件
9.6 KB, 下载次数: 60
阅读权限95
在线时间 小时
原帖由 Q5006 于
20:54 发表
谢谢老朽,如表格中的行是不断增加的,又如何改这个
& && &'撰写:老朽
& && &'网址:
& && &'日期: 下午 08:56:28
Sub zldccmx()
& & 'Dim RegEx As New RegExp
& & Set RegEx = CreateObject(&VBSCRIPT.REGEXP&)& & 'RegEx为建立正则表达式
& & RegEx.Global = True & &&&'设置全局可用
& & arr = [c2:C9] 'Array(&YJV-5*16&, &YJV22-5*16&, &VV-5*16&, &V22-5*16&, &BV-2*2.5&, &BV-3*2.5&, &BVV-2*2.5&, &BVV-3*2.5&)
& & For i = 1 To UBound (arr)
& & RegEx.Pattern = &-\S*\*& '取 - 与 *之间的部分
& & For Each b In RegEx.Execute(arr(i, 1)) '取返回结果
& && &&&RegEx.Pattern = &-|\*& '去除 - 和 *
& && &&&arr(i, 1) = RegEx.Replace(b, &&)
& &[f2:f9] = arr
阅读权限95
在线时间 小时
不用正则也许更简单:
& && &'撰写:老朽
& && &'网址:
& && &'日期: 下午 08:59:09
Sub zldccmx()
& & arr = [c2:C9]
& & For i = 1 To UBound (arr)
& && &&&arr(i, 1) = Split(Split(arr(i, 1), &*&)(0), &-&)(1)
& & [f2:f9] = arr
双Split,OK
阅读权限95
在线时间 小时
& & & & & & & &
5是一位数,非一定是5
则:-\S?\*
阅读权限70
在线时间 小时
& & Set RegEx = CreateObject(&VBSCRIPT.REGEXP&)
& & RegEx.Global = 1
& & arr = Array(&YJV-aa15a*16&, &YJV22-5kkk*16&, &VV-5*16&, &V22-5*16&, &BV-2*2.5&, &BV-3*2.5&, &BVV-2*2.5&, &BVV-3*2.5&)
& & For i = 0 To UBound(arr)
& & RegEx.Pattern = &\-.*?(\d+).*\*&
& & MsgBox RegEx.Execute(arr(i))(0).submatches(0)
[ 本帖最后由 figfig 于
21:34 编辑 ]
玩命加载中,请稍候
玩命加载中,请稍候
本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!
本站特聘法律顾问:徐怀玉律师 李志群律师
Powered bydeveloperWorks 社区
在数据库中查找文本数据是应用程序中很常见的方案。本文描述了如何扩展 DB2 以将用于正则表达式匹配的公用库集成到 DB2 中,以使该任务变得容易和更高效。
, 信息集成开发, IBM 德国
Knut Stolze开始从事 DB2 研究时,是作为访问学者加入到 IBM 硅谷实验室的(他在那里从事 DB2 Image Extender 方面的工作)。之后,他转向了 DB2 Spatial Extender V8,在两年多的时间里,他负责多项增强功能,以改善扩展器的实用性、性能以及与标准的一致性。
目前,他作为德国耶拿(Jena)大学的助教,在联邦数据库领域继续为 IBM 工作。可以通过新闻组 comp.databases.ibm-db2 和 ibm.software.db2.udb.spatial 或通过电子邮件
与他联系。
请注意:在阅读本文之前,请先阅读
简介在数据库中查找文本数据是应用程序中很常见的情形。有几种基于全文本的产品可用于 IBM(R) DB2(R) Universal Database™,包括 DB2 Text Information Extender 和 DB2 Net Search Extender。但是,DB2 Extenders(R) 不包括执行
正则表达式匹配的功能,该功能用来查找和替换字符串中的模式。本文描述了如何实现一个用户定义函数(UDF),该函数将普遍可用的正则表达式匹配库与 DB2 集成在一起。我们通过示例使用了
pcre 库(Perl 兼容的正则表达式),但也可以用任何其它库替换它。
本文中所提供的描述适用于 V7 和 V8 版本的 DB2 通用数据库的 Linux 版、UNIX(R) 版和 Windows(R) 版。背景知识本节描述了正则表达式是什么以及它们为什么有用。正则表达式是什么?正则表达式用于查找和替换字符串中的模式。正则表达式是用某种语法定义的,正则表达式引擎采用这种语法并将它与字符串进行比较。引擎返回字符串是否与语法匹配的指示;也即,该字符串是否包含能够从该语法派生的子串。此外,引擎还能够返回匹配的子串。术语“模式(pattern)”用来表示语法。最基本的模式仅由单个字母组成。当与该模式进行比较时,包含这个字母的字符串就是一个“匹配”。例如,如果模式是“a”,则字符串“abcd”就是一个匹配,而字符串“xyz”则不是。正则表达式的强大功能来自于预定义的运算符(也称为元字符),它们可以用很小的空间来表示模式。根据“方言”和受支持的功能,可以使用不同的元字符。通常,其中的一些可用字符如下:| — 二中择一
[ ] — 分组
* — 多次出现(也匹配零次出现)
+ — 多次出现(至少一次)
? — 随意的出现次数
\\\\ — 反斜杠不同的系统实现了常用正则表达式的各种扩展。编程语言 Perl 中使用的正则表达式支持进一步的缩写。本文中所用的库实现了这些扩展。下面摘录了其中部分可以在 Perl 正则表达式语言中使用的缩写:\\s — 任意空白字符
\\w — 任意字母数字字符
\\d — 任意数字字符另一个更高级的示例是模式“[A-Z]* = ([0-9]|0x00);”。与这个模式相匹配的字符串包含这样的子串:它由几个大写字母、后面跟上一个空格、一个等号、另一个空格,然后是一个数字或字符串“0x00”组成。该子串的最后一个字符必须是分号。使用 Perl,这个模式可以表示为“\\w* = (\\d|0x00);”。“NM = 0x00;”和“X = 7;”是两个可以与该模式匹配的字符串。但字符串“Z = 123;”不能匹配,因为 123 是由三个数字所组成的。DB2 中的字符串匹配除了 Extender 以外,DB2 还允许几种用于文本比较的函数和运算符。但那些函数和运算符要么在用于模式匹配的功能方面有限制,要么就是会给可能使用它们的查询带来复杂性。这里简要地摘录几个可用的功能:= 或 && 谓词:逐字符地比较两个字符串是否相等。
LIKE 谓词:使用通配符的基本模式匹配。
LOCATE 函数:在字符串中查找子串。
尽管也可以用 SQL 运算符表示模式“[A-Z]* = ([0-9]|0x00);”,但那样会很麻烦。例如,下列 SELECT 语句的 WHERE 子句中所使用的谓词会匹配字符串“str”中等号之后的部分,如
SELECT str
WHERE ( 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]*”子模式的谓词的复杂度,这可以使用对整个字符串进行迭代并进行逐字符比较的函数来完成,但您会发现使用内置功能既冗长又复杂。示例方案让我们定义下列清单(
)并插入几行:
CREATE TABLE strTable ( c1 INTEGER, str VARCHAR(500) );
INSERT INTO strTable VALUES ( 1, '' ),
( 2, 'variable = 1234;' ),
( 3, 'var2 = ''string variable'';' ),
( 4, 'xyz = ' ),
( 5, 'myVar = 0x00;' ),
( 6, '# comment' ),
( 7, 'abc = def' );这个
及其数据被用于下面的所有示例。
SELECT * FROM strT
----------- ------------------------------
2 variable = 1234;
3 var2 = 'string variable';
5 myVar = 0x00;
6 # comment
7 abc = def
7 record(s) selected.实现模式匹配函数您可以使用 DB2 的可扩展机制,在 SQL 语句内使用 UDF,以便显著地改善这种情形。通过定义名为 regex1 的 UDF(它采用模式和字符串作为输入参数),
中的 WHERE 子句现在可以写得象
中所示的那样:
SELECT str
WHERE regex1('\\w* = (\\d|0x00);', str) = 1在本示例中,使用带有 Perl 扩展的正则表达式来匹配完整的模式,而不仅仅是
中给出的 LIKE 谓词所对应的部分模式。正如您所看到的,使用函数来为该模式编写谓词比用 LIKE 谓词表示同样的语义要容易得多。
实现 UDF在我的示例实现中,我选择了现有的名为 PCRE(Perl 兼容的正则表达式,Perl-compatible regular expression)的模式匹配引擎。该引擎提供了用来处理模式和执行匹配的 C API。该引擎和查询中所用的 SQL 语言之间“缺失的部分”是 UDF。该 UDF 由两部分组成:在数据库中创建(或注册)该函数的 CREATE FUNCTION 语句。该函数的主体,它实现了用于正则表达式匹配引擎的 C API 调用的封装器显示了用于创建该函数的 SQL 语句。
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 EXTERNAL ACTION
ALLOW PARALLEL;注:请参阅
DB2 SQL Reference以获取所有子句的详细含义。可以修改参数的长度以适应您的需求。我在此处展示某些值并没有任何推荐使用它们的用意。
第二部分由一小段 C 代码组成,它实现了 UDF 入口点。在查询执行期间,DB2 为每个要与模式匹配的行调用这个入口点。
中的示例列出了该代码的清单。有关
pcre_* 函数和宏的描述,请参考 PCRE 库的文档。有关 C 代码的编译和共享库的构建,请参考
DB2 Application Development Guide。
#include &pcre.h&
#include &sqludf.h&
void regexpSimple(
// input parameters
SQLUDF_VARCHAR *pattern,
SQLUDF_CLOB *str,
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);
// 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;
case PCRE_ERROR_BADOPTION:
snprintf(SQLUDF_MSGTX, 70, "An unrecognized bit was set in the "
"options argument");
strcpy(SQLUDF_STATE, "38901");
case PCRE_ERROR_NOMEMORY:
snprintf(SQLUDF_MSGTX, 70, "Not enough memory available.");
strcpy(SQLUDF_STATE, "38902");
if (rc & 0) {
snprintf(SQLUDF_MSGTX, 70, "A regexp match error "
"occured: %d", rc);
strcpy(SQLUDF_STATE, "38903");
*match = 1;
// cleanup
(*pcre_free)(re);
}用法示例下列查询试图从表
strTable 中找出包含注释文本的所有字符串。注释以“#”开头,所以模式是“#”后跟非空文本。
SELECT c1, str
regex1('#\\s*\\w+', str) = 1;结果只包含 c1 = 6 的行。C1
----------- -------------------------
1 record(s) selected.在第二个示例中,我们试图找到这种赋值形式的字符串;即“text = text”。为了进一步缩小范围,我们只查找那些右端为数值的赋值。将十六进制表示法作为有效数值对待。SELECT c1, str
regex1('\\w+\\s*=\\s*(\\d+|0x\\d\\d)', str) = 1;除了 c1 为 2 或 5 的两行以外,其它行都不包含数值的赋值,因此不会出现在结果中:C1
----------- -------------------------
2 variable = 1234;
5 myVar = 0x00;
2 record(s) selected.改进性能尽管上面的函数按照预期的方式工作,但还可以改进它以获得更佳的性能。注:函数内部的执行完成得越快,DB2 处理整个 SQL 语句的速度也就越快。SQL 旨在处理多组行,这意味着通常会针对一个模式匹配多个行。在大多数情况下,模式本身对于整个 SQL 语句都是不变的;即,它不会随行的更改而更改。
中的 C 代码展示了对每一行都调用函数
pcre_compile() ,该函数将给定模式转换成内部表示法。
DB2 通过使用所谓的“高速暂存(scratchpad)”提供了在 UDF 调用之间传递信息的机制。此外,您可以标识特定调用“类型”;即它是对该 UDF 的第一次调用、普通调用还是最后一次(最终)调用。使用高速暂存和调用类型,有可能只对模式编译一次,然后将该已编译模式的内部表示法重用于对该 UDF 的所有后续调用。在最后一次调用时,释放在处理期间分配的资源。如
所示,对 CREATE FUNCTION 语句进行修改,告诉 DB2 向外部 C 代码提供高速暂存和调用类型:
CREATE FUNCTION regex2(pattern VARCHAR(2048), string CLOB(10M))
RETURNS INTEGER
SPECIFIC regexPerf
EXTERNAL NAME 'regexUdf!regexpPerf'
LANGUAGE C
PARAMETER STYLE DB2SQL
DETERMINISTIC
NOT FENCED
RETURNS NULL ON NULL INPUT
NO EXTERNAL ACTION
SCRATCHPAD 50
FINAL CALL
ALLOW PARALLEL;UDF 入口点看起来很不一样,因为必须改写函数内部的逻辑。参数方面唯一的更改是使用
SQLUDF_TRAIL_ARGS_ALL 代替了
SQLUDF_TRAIL_ARGS ,如
#include &pcre.h&
#include &sqludf.h&
// data structure mapped on the scratchpad for easier use and access
// to the objects
// the size of the scratchpad defined in the CREATE FUNCTION statement
// must be at least as large as sizeof(scratchPadMapping)
struct scratchPadMapping {
pcre_extra *
const char *
void regexpPerf(
// input parameters
SQLUDF_VARCHAR *pattern,
SQLUDF_CLOB *str,
SQLUDF_INTEGER *match,
// null indicators
SQLUDF_NULLIND *pattern_ind,
SQLUDF_NULLIND *str_ind,
SQLUDF_NULLIND *match_ind,
SQLUDF_TRAIL_ARGS_ALL) // SQLUDF_SCRAT & SQLUDF_CALLT
int rc = 0;
struct scratchPadMapping *scratch = NULL;
// map the buffer of the scratchpad and assume successful return
scratch = (struct scratchPadMapping *)SQLUDF_SCRAT-&
*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-&errOffset = 0;
// compile the pattern (only in the FIRST call
scratch-&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: %s\\n", scratch-&errOffset, scratch-&error);
strcpy(SQLUDF_STATE, "38900");
// 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 result
already in the FIRST call */
case SQLUDF_NORMAL_CALL:
// match the current string
rc = pcre_exec(scratch-&re, scratch-&extra, str-&data,
str-&length, 0, 0 /* default options */, NULL, 0);
switch (rc) {
case PCRE_ERROR_NOMATCH:
*match = 0;
case PCRE_ERROR_BADOPTION:
snprintf(SQLUDF_MSGTX, 70, "An unrecognized bit was set "
"in the options argument");
strcpy(SQLUDF_STATE, "38901");
case PCRE_ERROR_NOMEMORY:
snprintf(SQLUDF_MSGTX, 70, "Not enough memory available.");
strcpy(SQLUDF_STATE, "38902");
if (rc & 0) {
snprintf(SQLUDF_MSGTX, 70, "A regexp match error "
"occured: %d", rc);
strcpy(SQLUDF_STATE, "38903");
*match = 1;
// cleanup in FINAL call, or if we encountered an error in
// the FIRST call (DB2 will make a FINAL call if we encounter
// an error in any NORMAL call)
if (SQLUDF_CALLT == SQLUDF_FINAL_CALL ||
(SQLUDF_CALLT == SQLUDF_FIRST_CALL && rc & 0)) {
(*pcre_free)(scratch-&re);
(*pcre_free)(scratch-&extra);
}为了进一步改进该函数的性能,我添加了对函数
pcre_study() 的调用,该函数是由模式匹配引擎提供的。该函数进一步分析了该模式,并将额外的信息存储在独立的结构中。然后,在实际的匹配期间使用这些额外的信息来加快处理速度。通过使用一个非常简单的模式和大约 4000 行的表,我获得了 5% 的执行时间的改善。当然,模式越复杂,差异将越显著。
我先前提到该实现假定模式在处理期间不会随行的不同而更改。当然,如果模式确实更改了,您可以进行少量的改写以再次编译一个模式。要这样做,有必要跟踪当前(已编译的)模式并在每次调用中将它与所提供的模式进行比较。也可以在高速暂存中维护当前模式。但必须将它复制到独立的缓冲区,并且不能通过指针模式直接引用它,因为这个指针或它所引用的数据可能会更改或变为无效。至于相应的代码更改,就当作练习留给读者了。返回匹配子串大多数模式匹配引擎提供了一种方法,返回与指定模式或其一部分相匹配的子串。如果想在 SQL 中使用这种能力,则必须使用不同的方法来实现匹配函数。给定的字符串可能包含不止一个匹配的子串。例如,当解析类似“abc = 123;”或“def = 'some text';”这样的字符串时,用户可能会希望检索由等号分隔的两个子串。您可以使用模式“\\w+\\s*=\\s*(\\d+|'[\\w\\s]*');”来表示适用于该字符串的语法规则。Perl 兼容的正则表达式允许您捕获等号两边的子串。最后,必须将要捕获的子串用括号括起来。我已经用该方式编写了第二个子串,但第一个子串不是这样编写的。用于该用途的最终模式是这样的:(\\w+)\\s*=\\s*(\\d+|'[\\w\\s]*');当把这个模式应用于字符串“abc= 123;”或“def = 'some text';”时,“abc”或“def”分别与“(\\w+)”匹配,空格和等号是通过“\\s*=\\s*”查找的,并用另外的“(\\d+|'[\\w\\s*]')”涵盖了余下的子串。在“(\\d+|'[\\w\\s*]')”中,第一个选项与任何至少由一个数字“\\d+”组成的数匹配,而第二个选项解析任何由字母和空格组成的由单引号括起的字符串“'[\\w\\s]*'”。在 DB2 中做到这一点的需求可以描述成:为一次 UDF 调用返回多个结果。换句话说,就是返回针对模式进行匹配的单个字符串的多个子串。DB2 的表函数是完成这一任务的完美工具。实现表 UDF和以前一样,必须在数据库中创建该函数。
中的下列语句正是用于这一任务的:
CREATE FUNCTION regex3(pattern VARCHAR(2048), string CLOB(10M))
RETURNS TABLE ( position INTEGER, substring VARCHAR(2048) )
SPECIFIC regexSubstr
EXTERNAL NAME 'regexUdf!regexpSubstr'
LANGUAGE C
PARAMETER STYLE DB2SQL
DETERMINISTIC
NOT FENCED
RETURNS NULL ON NULL INPUT
NO EXTERNAL ACTION
SCRATCHPAD 50
NO FINAL CALL
DISALLOW PARALLEL;实现该函数的实际逻辑的 C 代码与
中的代码非常相似,但根据表函数所必须满足的特殊需求对它进行了改编,如
#include &pcre.h&
#include &sqludf.h&
#include &sqlstate.h&
#include &string.h&
struct scratchPadMapping {
pcre_extra *
const char *
int currentS
void regexpSubstr(
// input parameters
SQLUDF_VARCHAR *pattern,
SQLUDF_CLOB *str,
SQLUDF_INTEGER *pos,
SQLUDF_VARCHAR *substr,
// null indicators
SQLUDF_NULLIND *pattern_ind,
SQLUDF_NULLIND *str_ind,
SQLUDF_NULLIND *pos_ind,
SQLUDF_NULLIND *substr_ind,
SQLUDF_TRAIL_ARGS_ALL) // SQLUDF_SCRAT & SQLUDF_CALLT
int rc = 0;
size_t length = 0;
struct scratchPadMapping *scratch = NULL;
// map the buffer of the scratchpad and assume NULL return
scratch = (struct scratchPadMapping *)SQLUDF_SCRAT-&
*pos_ind = 0;
*substr_ind = 0;
switch (SQLUDF_CALLT) {
case SQLUDF_TF_OPEN:
// initialize data on the scratchpad
scratch-&re = NULL;
scratch-&extra = NULL;
scratch-&error = NULL;
scratch-&errOffset = 0;
scratch-&numSubstr = 0;
scratch-&substr = NULL;
scratch-&currentSubstr = 1; // skip the complete match
// compile the pattern (only in the FIRST call
scratch-&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: %s\\n", scratch-&errOffset, scratch-&error);
strcpy(SQLUDF_STATE, "38900");
// further analyze the pattern (might return NULL)
scratch-&extra = pcre_study(scratch-&re,
0 /* default options */, &scratch-&error);
// determine the number of capturing subpatterns
rc = pcre_fullinfo(scratch-&re, scratch-&extra,
PCRE_INFO_CAPTURECOUNT, &scratch-&numSubstr);
snprintf(SQLUDF_MSGTX, 70, "Could not retrieve info "
"on pattern. (rc = %d)", rc);
strcpy(SQLUDF_STATE, "38901");
// allocate memory for the substring indices
int size = (scratch-&numSubstr+1)*3;
scratch-&substr = (int *)malloc(size * sizeof(int));
if (!scratch-&substr) {
snprintf(SQLUDF_MSGTX, 70, "Could allocate memory for "
"substring indices.");
strcpy(SQLUDF_STATE, "38902");
memset(scratch-&substr, 0, size * sizeof(int));
// match the current string
rc = pcre_exec(scratch-&re, scratch-&extra, str-&data,
str-&length, 0, 0 /* default options */,
scratch-&substr, size);
switch (rc) {
case PCRE_ERROR_BADOPTION:
snprintf(SQLUDF_MSGTX, 70, "An unrecognized bit was set "
"in the options argument");
strcpy(SQLUDF_STATE, "38903");
case PCRE_ERROR_NOMEMORY:
snprintf(SQLUDF_MSGTX, 70, "Not enough memory available.");
strcpy(SQLUDF_STATE, "38904");
case PCRE_ERROR_NOMATCH:
scratch-&currentSubstr = scratch-&numSubstr + 1;
if (rc & 0) {
snprintf(SQLUDF_MSGTX, 70, "A regexp match error "
"occured: %d", rc);
strcpy(SQLUDF_STATE, "38905");
case SQLUDF_TF_FETCH:
// skip capturing substrings without a match
while (scratch-&currentSubstr &= scratch-&numSubstr &&
(scratch-&substr[2*scratch-&currentSubstr] & 0 ||
scratch-&substr[2*scratch-&currentSubstr+1] & 0)) {
scratch-&currentSubstr++;
// no more data to be returned
if (scratch-&currentSubstr & scratch-&numSubstr) {
strcpy(SQLUDF_STATE, SQL_NODATA_EXCEPTION);
// get the current substring
*pos = scratch-&currentS
length = scratch-&substr[2*scratch-&currentSubstr+1] -
scratch-&substr[2*scratch-&currentSubstr];
strncpy(substr, str-&data + scratch-&substr[2*scratch-&currentSubstr],
substr[length] = '\\0';
scratch-&currentSubstr++;
// cleanup in CLOSE call, or if we encountered an error in
// the OPEN call (DB2 will make a CLOSE call if we encounter
// an error in any FETCH call)
if (SQLUDF_CALLT == SQLUDF_TF_CLOSE ||
(SQLUDF_CALLT == SQLUDF_TF_OPEN && rc & 0)) {
(*pcre_free)(scratch-&re);
(*pcre_free)(scratch-&extra);
free(scratch-&substr);
}正如我们对基本匹配函数所做的那样,您也可使用 FINAL CALL 定义表函数来改进性能。必须修改 C 代码以处理 SQLUDF_TF_FIRST 和 SQLUDF_TF_FINAL 调用。用法示例表函数可以在类似于如下所示的 SELECT 语句中使用:SELECT c1, str, num, substr
TABLE ( regex3('(\\w+)\\s*=\\s*(\\d+|''[\\w\\s]*'');', str) ) AS sub(num, substr)结果只包括拥有匹配模式的字符串。对于每个字符串,都在单独的行中显示所捕获的第一个和第二个子串。C1
----------- ------------------------------ ----------- -----------------------
2 variable = 1234;
1 variable
2 variable = 1234;
3 var2 = 'string variable';
3 var2 = 'string variable';
2 'string variable'
4 record(s) selected.下一个查询在结果集中用单独的列而不是单独的行返回这两个子串对。这样,用 SQL 语句进一步处理这些字符串以及它们的子串要容易些。该查询使用了公共表表达式(由关键字
WITH 表示)来确保在整个查询中只对每个字符串进行一次求值,而不是在中间表
s2 所需的每次子选择中都进行一次求值。
WITH substrings(c, num, substr) AS
( SELECT c1, num, substr
TABLE ( regex3('(\\w+)\\s*=\\s*(\\d+|''[\\w\\s]*'');', str) )
AS sub(num, substr) )
SELECT t.c1, s1.substr AS variable, s2.substr AS value
strTable AS t JOIN substrings AS s1 ON
( t.c1 = s1.c ) JOIN
substrings AS s2 ON
( t.c1 = s2.c )
s1.num = 1 AND s2.num = 2这里使用了与前面查询中相同的模式。因此,可以从上面的表中派生出结果,但这一次,根据请求,这些 variable-value 对每个都位于单独的行中。C1
----------- ------------------------------ --------------------
2 variable
'string variable'
2 record(s) selected.结束语在本文中,我相当简略地介绍了正则表达式以及 DB2 中可用的字符串比较和匹配功能。我还描述了为什么正则表达式的强大功能是如此有用。UDF 可以用来以两种形式在 DB2 中提供正则表达式。在第一种形式中,通过将字符串与给定模式进行比较来完成基本匹配。第二种形式是实现表函数,它从正则表达式抽取已捕获的子串,并将这些子串返回给 DB2,以便用在 SQL 语句的进一步处理中。我还给出了一些关于如何改进性能的提示。参考资料位于
DB2 Application Development Guide位于
DB2 SQL Reference位于
Larry Wall、Jon Orwant 和 Tom Christiansen 合著的
Programming Perl,第 3 版,2000 年 7 月。
免责声明本文包含了样本代码。IBM 授予您(“被许可方”)使用这个样本代码的非专有的、版权免费的许可证。然而,该样本代码是以“按现状”的基础提供的,没有任何形式的(不论是明示的,还是默示的)保证,包括对适销性、适用于特定用途或非侵权性的默示保证。IBM 及其许可方不对被许可方由于使用该软件所导致的任何损失负责。任何情况下,无论损失是如何发生的,也不管责任条款怎样,IBM 或其许可方都不对由使用该软件或不能使用该软件所引起的收入的减少、利润的损失或数据的丢失,或者直接的、间接的、特殊的、由此产生的、附带的损失或惩罚性的损失赔偿负责,即使 IBM 已经被明确告知此类损害的可能性,也是如此。
developerWorks: 登录
标有星(*)号的字段是必填字段。
保持登录。
单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件。
在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。
所有提交的信息确保安全。
选择您的昵称
当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。昵称长度在 3 至 31 个字符之间。
您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。
标有星(*)号的字段是必填字段。
(昵称长度在 3 至 31 个字符之间)
单击提交则表示您同意developerWorks 的条款和条件。 .
所有提交的信息确保安全。
IBM PureSystems(TM) 系列解决方案是一个专家集成系统
通过学习路线图系统掌握软件开发技能
软件下载、试用版及云计算
static.content.url=/developerworks/js/artrating/SITE_ID=10Zone=Information ManagementArticleID=57604ArticleTitle=将正则表达式匹配的强大功能带给 SQLpublish-date=

我要回帖

更多关于 正则表达式排除字符串 的文章

 

随机推荐