Oracle REGEXP_LIKE 和字边界

Posted

技术标签:

【中文标题】Oracle REGEXP_LIKE 和字边界【英文标题】:Oracle REGEXP_LIKE and word boundaries 【发布时间】:2011-11-25 22:21:18 【问题描述】:

我在使用 REGEXP_LIKE 匹配单词边界时遇到问题。以下查询按预期返回单行。

select 1 from dual
where regexp_like('DOES TEST WORK HERE','TEST');

但我也想匹配单词边界。因此,添加“\b”字符会给出此查询

select 1 from dual
where regexp_like('DOES TEST WORK HERE','\bTEST\b');

运行此返回零行。有什么想法吗?

【问题讨论】:

这很奇怪。我也无法让它工作...例如,select regexp_replace('DOES TEST WORK HERE','\bTEST\b','X') from dual; 返回DOES TEST WORK HERE...如果您使用\W,它可以工作,但这与\b 不同:P 【参考方案1】:

相信你也想试试

 select 1 from dual 
  where regexp_like ('does test work here', '(^|\s)test(\s|$)');

因为\b 未出现在此列表中:Perl-influenced Extensions in Oracle Regular Expressions

\s 确保测试以空格开始和结束。然而,这还不够,因为字符串test 也可能出现在被匹配字符串的开头或结尾。因此,我使用 alternative(由 | 表示)^ 用于字符串的开头,$ 用于字符串的结尾。

更新(3 年后)... 碰巧,我今天需要这个功能,在我看来,更好的正则表达式是(^|\s|\W)test($|\s|\W) (The missing \b regular expression special character in Oracle)。

【讨论】:

谢谢。我在网上找到了很多资源(例如 psoug.org/snippet/… ),建议您可以。我实际上想匹配字符串的开头或结尾,或者在我的情况下是“非单词”字符 - 所以我用 \W 代替 \s。 是的,Oracle 似乎选择不支持\b,尽管这是一个相当标准的正则表达式标记。 Oracle 的正则表达式使用不支持单词边界的 POSIX ERE 标准(具有一些增强功能,例如反向引用)。 在您更新的正则表达式中,\s 字符类是多余的,因为您包含了\W(一个字符类,它是\s 的超集)。【参考方案2】:

可以在Oracle中检查整个单词的最短正则表达式是

(^|\W)test($|\W)

请参阅regex demo。

详情

(^|\W) - 一个匹配的捕获组 ^ - 字符串开头 | - 或 \W - 非单词字符 test - 一句话 ($|\W) - 一个匹配的捕获组 $ - 字符串结束 | - 或 \W - 非单词字符。

注意\W 匹配除字母、数字和_ 之外的任何字符。如果你想匹配一个可以出现在_(下划线)之间的单词,你需要一个稍微不同的模式:

(^|[^[:alnum:]])test($|[^[:alnum:]])

[^[:alnum:]] 否定括号表达式匹配除字母数字字符以外的任何字符,并匹配 _,因此,_test_ 将与此模式匹配。

见this regex demo。

【讨论】:

【参考方案3】:

一般来说,我会坚持 René 的解决方案,但当您需要匹配为零长度时例外。即您不想在开头/结尾处实际捕获非单词字符。

例如,如果我们的字符串是test test,那么(\b)test(\b) 将匹配两次,但(^|\s|\W)test($|\s|\W) 只会匹配第一次出现。至少,如果您尝试使用 regexp_substr,情况肯定是这样。

例子

SELECT regexp_substr('test test', '(^|\s|\W)test($|\s|\W)', 1, 1, 'i'), regexp_substr('test test', '(^|\s|\W)test($|\s|\W)', 1, 2, 'i') FROM dual;

返回

test |NULL

【讨论】:

但是 OP 的观点是零长度字边界 \b 在 Oracle 中不起作用。正如在其他答案中的 cmets 中所解释的那样。而且由于没有前瞻支持,我们也找不到重叠的匹配项......所以我们永远无法在字符串“some string testtest some string”中找到两个“test”匹配项。

以上是关于Oracle REGEXP_LIKE 和字边界的主要内容,如果未能解决你的问题,请参考以下文章

Oracle:Oracle 8i 中 REGEXP_LIKE 函数的替代方案

oracle通过添加regexp_like将字符串连接到数字不起作用

oracle regexp_like介绍和例子

oracle regexp_like 与 select 模式

Oracle regexp_like - 只有某些字符、数字和一个符号

oracle正则表达式regexp_like的用法详解