【问题标题】:Oracle SQL regexp_replace stops at OR groupOracle SQL regexp_replace 在 OR 组处停止
【发布时间】:2019-09-02 09:35:28
【问题描述】:

我尝试使用 oracle SQL regexp_replace 过滤 URL 列表中的域名。问题似乎是其中一些确实有端口,而另一些则没有。

从以下示例中,the-super.hosting.com 应替换为 HOSTNAME(但不要在正则表达式中硬编码,因为可能有任何内容) p>

WITH strings AS (   
  SELECT 'http://wwww11.the-super.hosting.com:9999/aPath/servlet?config=abcLoginNr=%1' s FROM dual union all   
  SELECT 'http://wwww22.the-super.hosting.com:6666/aPath/servlet?config=abcLoginNr=%2' s FROM dual union all   
  SELECT 'http://wwww22.the-super.hosting.com:6666/aPath/servlet?config=abcLoginNr=%2' s FROM dual union all   
  SELECT 'http://wwww04.the-super.hosting.com/aPath/servlet?config#here' s FROM dual   
)  
  SELECT regexp_replace(s,'([[:alpha:]]+://[[:alpha:]]{4}[[:digit:]]{2}\.)(.+)(:9999/|:6666/|/?)(.+)', '\1HOSTNAME\3\4') "MODIFIED_STRING", s "STRING"
  FROM strings;

它似乎无法使用普通路径将端口作为可选处理(因为路径直接从那里开始)。
是否可以以不同的方式匹配域部分,以便始终留下带有可选端口的路径?
有没有办法用一个语句替换它?

【问题讨论】:

  • 我认为首先(.+) 应该是([^/]+?)

标签: sql regex oracle replace


【解决方案1】:

我认为你让它变得更复杂了。你只需要三个部分;初始协议(:// 后面的任何内容)和 www??. 前缀(假设它实际上始终存在);要删除的其余域名;以及剩下的一切,可能包括也可能不包括端口——但你并不在乎;所以:

([^.]+\.)([^/:]+)(.*)

在哪里

  • ([^.]+\.) 是协议和所有内容,包括域名中的第一个点;
  • ([^/:]+) 可以是斜杠或冒号
  • (.*) 是其余的

对于替换,您希望保持第一和第三部分不变,并用您固定的HOSTNAME 替换第二部分。

所以你得到:

WITH strings AS (
  SELECT 'http://wwww11.the-super.hosting.com:9999/aPath/servlet?config=abcLoginNr=%1' s FROM dual union all
  SELECT 'http://wwww22.the-super.hosting.com:6666/aPath/servlet?config=abcLoginNr=%2' s FROM dual union all
  SELECT 'http://wwww22.the-super.hosting.com:6666/aPath/servlet?config=abcLoginNr=%2' s FROM dual union all
  SELECT 'http://wwww04.the-super.hosting.com/aPath/servlet?config#here' s FROM dual union all
  SELECT 'http://wwww04.the-super.hosting.com' s FROM dual union all
  SELECT 'http://wwww04.the-super.hosting.com/' s FROM dual union all
  SELECT 'http://wwww04.the-super.hosting.com/aPath' s FROM dual union all
  SELECT 'http://wwww04.the-super.hosting.com:1234' s FROM dual union all
  SELECT 'http://wwww04.the-super.hosting.com:1234/' s FROM dual union all
  SELECT 'http://wwww04.the-super.hosting.com:1234/aPath' s FROM dual
)  
SELECT regexp_replace(s, '([^.]+\.)([^/:]+)(.*)', '\1HOSTNAME\3') "MODIFIED_STRING", s "STRING"
FROM strings;

MODIFIED_STRING                                                STRING                                                                     
-------------------------------------------------------------- ---------------------------------------------------------------------------
http://wwww11.HOSTNAME:9999/aPath/servlet?config=abcLoginNr=%1 http://wwww11.the-super.hosting.com:9999/aPath/servlet?config=abcLoginNr=%1
http://wwww22.HOSTNAME:6666/aPath/servlet?config=abcLoginNr=%2 http://wwww22.the-super.hosting.com:6666/aPath/servlet?config=abcLoginNr=%2
http://wwww22.HOSTNAME:6666/aPath/servlet?config=abcLoginNr=%2 http://wwww22.the-super.hosting.com:6666/aPath/servlet?config=abcLoginNr=%2
http://wwww04.HOSTNAME/aPath/servlet?config#here               http://wwww04.the-super.hosting.com/aPath/servlet?config#here              
http://wwww04.HOSTNAME                                         http://wwww04.the-super.hosting.com                                        
http://wwww04.HOSTNAME/                                        http://wwww04.the-super.hosting.com/                                       
http://wwww04.HOSTNAME/aPath                                   http://wwww04.the-super.hosting.com/aPath                                  
http://wwww04.HOSTNAME:1234                                    http://wwww04.the-super.hosting.com:1234                                   
http://wwww04.HOSTNAME:1234/                                   http://wwww04.the-super.hosting.com:1234/                                  
http://wwww04.HOSTNAME:1234/aPath                              http://wwww04.the-super.hosting.com:1234/aPath                             

您可以更明确地了解协议格式等,但我不确定是否有什么意义。


您的原始模式的问题是贪婪和可选斜杠作为带有端口号的最终“或”组件的混合。您可以对其进行调整以使其正常工作,至少对于您的示例数据,例如:

WITH strings AS (   
  SELECT 'http://wwww11.the-super.hosting.com:9999/aPath/servlet?config=abcLoginNr=%1' s FROM dual union all   
  SELECT 'http://wwww22.the-super.hosting.com:6666/aPath/servlet?config=abcLoginNr=%2' s FROM dual union all   
  SELECT 'http://wwww22.the-super.hosting.com:6666/aPath/servlet?config=abcLoginNr=%2' s FROM dual union all   
  SELECT 'http://wwww04.the-super.hosting.com/aPath/servlet?config#here' s FROM dual   
)  
SELECT regexp_replace(s,'([[:alpha:]]+://[[:alpha:]]{4}[[:digit:]]{2}\.)(.+?)(:9999/|:6666/|/)(.+)$', '\1HOSTNAME\3\4') "MODIFIED_STRING", s "STRING"
--                                                                         ^               ^^^    ^
FROM strings;

MODIFIED_STRING                                                STRING                                                                     
-------------------------------------------------------------- ---------------------------------------------------------------------------
http://wwww11.HOSTNAME:9999/aPath/servlet?config=abcLoginNr=%1 http://wwww11.the-super.hosting.com:9999/aPath/servlet?config=abcLoginNr=%1
http://wwww22.HOSTNAME:6666/aPath/servlet?config=abcLoginNr=%2 http://wwww22.the-super.hosting.com:6666/aPath/servlet?config=abcLoginNr=%2
http://wwww22.HOSTNAME:6666/aPath/servlet?config=abcLoginNr=%2 http://wwww22.the-super.hosting.com:6666/aPath/servlet?config=abcLoginNr=%2
http://wwww04.HOSTNAME/aPath/servlet?config#here               http://wwww04.the-super.hosting.com/aPath/servlet?config#here              

但这似乎有点矫枉过正。

【讨论】:

  • 真的很好 - 我选择你的第一个解决方案而不是我改进的解决方案 - 看起来更简单。只剩下一个问题了。为什么输出字符串中需要点?我认为它将用于第一个模式匹配部分。
  • @PaulEdison - 我用于第一组的模式是除了点之外的任何东西,所以第一个点进入第二组 - 因此必须成为替换的一部分。不过,您可以这样做;我已将其更新为将其包含在第一组中,因此它不是第二组的一部分,也不需要成为固定替换字符串的一部分。
猜你喜欢
  • 2018-09-20
  • 2016-06-13
  • 1970-01-01
  • 2019-06-25
  • 2014-05-28
  • 2018-06-23
  • 1970-01-01
  • 2016-08-31
  • 1970-01-01
相关资源
最近更新 更多