Oracle 11g - REGEXP_REPLACE - 子表达式/不同的匹配

Posted

技术标签:

【中文标题】Oracle 11g - REGEXP_REPLACE - 子表达式/不同的匹配【英文标题】:Oracle 11g - REGEXP_REPLACE - Subexpressions/different matches 【发布时间】:2018-08-29 16:11:45 【问题描述】:

SQLFiddle:http://sqlfiddle.com/#!4/db1bd/49/0

我正在处理一个返回对象 DN:(cn=name,ou=folder,dc=hostname,dc=com)的查询

我的目标是在类似于 AD:(name\folder\hostname.com) 的“更漂亮”的输出中返回此信息

我以一种笨拙的方式完成了这项工作:

REGEXP_REPLACE(REGEXP_REPLACE(TEST, '.*CN=(.+?),DC=.*', '\1', 1, 1, 'i'), ',OU=', '\', 1, 0, 'i') -- grab everything between CN= and DC=, replace with \'s --
|| '\' || 
REGEXP_REPLACE(SUBSTR(TEST, REGEXP_INSTR(TEST, ',DC=', 1, 1, 0, 'i')+4),',DC=','.', 1, 0, 'i') -- grab everything after DC=, replace with .'s --

虽然这可行,但我对它的复杂程度并不感到兴奋(并且它涉及必须将两个正则表达式字符串缝合在一起)。

我开始干净利落,并意识到我为得到我想要的东西做的太多了,我的起点现在在这里:

REGEXP_REPLACE(test, '(,?(cn=|ou=)(.+?),)', '\3\')

认为我非常了解这个是如何工作的,但是如果我添加一个额外的 (...) 它会破坏我已经工作的内容并返回整个字符串。我读过 Oracle 的正则表达式引擎不如其他引擎先进,但我很难掌握评估事物的顺序。

示例输入(可以有多个 OU/DC):

cn=name,ou=subgroup,ou=group,dc=accounts,dc=hostname,dc=com cn=name,ou=group,dc=hostname,dc=com

预期输出

name\subgroup\group\accounts.hostname.com name\group\hostname.com

传入的数据是动态的,而不是固定数量的 OU 或 DC。

【问题讨论】:

sqlfiddle.com/#!4/db1bd/67/0 怎么样?你没有指定预期的输出,所以我只是猜测这就是你要找的。​​span> @ctwheels 预期的输出格式在上面列出:name\folder\hostname.com 如果有超过 2 个 (dc=),您的示例将不起作用:cn=name,ou=hello,dc=accounts,dc=hostname,dc=com 而是将它们组合在一起 name\hello\accountshostname.com。我开始认为这无法通过单个 REGEXP_REPLACE 来完成,并且需要多个(如您的示例)。 问题陈述不清楚。看来您想用反斜杠替换(大多数),xx=;但最后,您似乎想用点代替,而不是反斜杠。 dc 属性似乎就是这种情况,除了在最后一个示例字符串中有五个值,全部用于cn(该字符串中没有dc)。所以 - 如果你需要帮助,你需要准确地解释你需要什么。 @mathguy 提供了输入示例和预期输出。希望对您有所帮助。 @Wiktor Stribiżew 这正是我一直在寻找的,以及一些保证,这不能只用一个正则表达式来完成。感谢您的帮助。 【参考方案1】:

你可以使用

SELECT REPLACE(
    REGEXP_REPLACE(
        test, 
        '(^|,)(cn|ou)=([^,]*)(,dc=)?', 
        '\3\\'), 
    ',dc=', 
    '.') 
FROM regexTest

请参阅SQLFiddle。

第一个(^|,)(cn|ou)=([^,]*)(,dc=)? 正则表达式匹配, 或字符串开头,然后匹配cnou,然后是=,然后将除逗号之外的零个或多个字符捕获到第3 组中,然后匹配一个可选,dc= 子字符串(因此,删除,dc= 的第一个实例)。替换的是第 3 组内容和一个反斜杠。

所以,第二个操作很简单,只需将所有,dc= 替换为.,你甚至不需要正则表达式。

【讨论】:

【参考方案2】:

可能是这样的:

SELECT nvl(regexp_replace(
    regexp_replace(
      nullif(
        regexp_replace(test, '^cn=(.+?),DC=(.+?)$', '\1 \2',1,1,'i') 
        , test
      ) , ' |,(CN|OU)=', '\\', 1, 0,'i'
    ), ',DC=', '.', 1, 0,'i'
    ),test) result
FROM regexTest

如果没有DC=,此查询不会更改输入。

【讨论】:

以上是关于Oracle 11g - REGEXP_REPLACE - 子表达式/不同的匹配的主要内容,如果未能解决你的问题,请参考以下文章

Oracle 11g单实例RMAN恢复到Oracle 11g RAC

完全卸载oracle11g

Oracle 10g,和 Oracle 11g 能互相兼容吗?还是向下兼容?

oracle 11g怎样配置才能连接远程数据库

如何完全卸载Oracle 11g数据库

oracle 11g ocp 笔记-- oracle 11g体系结构概述