【问题标题】:Oracle REGEXP_LIKE and word boundariesOracle REGEXP_LIKE 和字边界
【发布时间】: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

标签: regex oracle word-boundary


【解决方案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”匹配项。
    猜你喜欢
    • 2017-05-02
    • 1970-01-01
    • 2015-05-30
    • 2013-05-12
    • 1970-01-01
    • 1970-01-01
    • 2010-11-28
    • 1970-01-01
    • 2017-07-21
    相关资源
    最近更新 更多