Oracle中的正則表達式(及函數)詳解

原文鏈接

1、概述

    相信大家對正則表達式都不陌生,從Linux下的命令到Java等編程語言,正則表達式無處不在,雖然我們實際使用的時候也並不一定太多,但是當我們要處理字符串時,它確實是一個強大的工具。

    上一篇文章(Oracle中的字符串類型及相關函數詳解)中,已經介紹了一些串相關的函數,也列出了用於正則表達式的函數,本文就正式介紹他們。

    本文基於Oracle 12c ,可能部分內容在較老的版本中不適用。

    運算符

    在介紹函數前,這裏先說明一下Oracle中正則表達式運算符及其描述。

    如果不知道他們有什麼用,或者也不知道描述說的是什麼,沒關係,可以先看後面的介紹,就知道他們的含義了。

運算符

    合理的使用這些運算符,配合正則表達式相關的函數,不但可以讓字符串處理變得更加高效,還能大大的減少代碼量。


2、相關函數

    統一說明: 

        函數中pattern爲正則表達式,最多可以包含512個字節。

        下面的介紹中,及時是不同的函數,如若參數描述字符串相同,即他們的意思也是相同的(如regexp_substr函數和regexp_instr函數中的position意思都是表示開始搜索的位置),爲了內容緊湊,只在那個參數第一次出現的地方作介紹。

        參數帶char的表示簡單的串類型,帶string的可以包含大對象串類型(如clob)。

        慣例,“[]”表示可選參數。

    2.1、REGEXP_SUBSTR

    REGEXP_SUBSTR函數使用正則表達式來指定返回串的起點和終點。

    語法:

  1. regexp_substr(source_string,pattern[,position[,occurrence[,match_parameter]]])

    source_string:源串,可以是常量,也可以是某個值類型爲串的列。

    position:從源串開始搜索的位置。默認爲1。

    occurrence:指定源串中的第幾次出現。默認值1.

    match_parameter:文本量,進一步訂製搜索,取值如下:

  •     'i'     用於不區分大小寫的匹配。
  •     'c'    用於區分大小寫的匹配。
  •     'n'    允許將句點“.”作爲通配符來匹配換行符。如果省略改參數,句點將不匹配換行符。
  •     'm'   將源串視爲多行。即將“^”和“$”分別看做源串中任意位置任意行的開始和結束,而不是看作整個源串的開始或結束。如果省略該參數,源串將被看作一行來處理。
  •     如果取值不屬於上述中的某個,將會報錯。如果指定了多個互相矛盾的值,將使用最後一個值。如'ic'會被當做'c'處理。
  •     省略該參數時:默認區分大小寫、句點不匹配換行符、源串被看作一行。

    例1:

  1. select regexp_substr('MY INFO: Anxpp,22,and boy','my',1,1,'i') from users;

    將返回MY,如果將match_parameter改爲'c'將不反悔任何內容(null)。

    例2:

  1. select regexp_substr('MY INFO: Anxpp,23,and boy','[[:digit:]]',1,2) from users;

    此處會返回3。

    注意這裏同時用到了“[]”和“[:digit:]”。

    2.2、REGEXP_INSTR

    REGEXP_INSTR函數使用正則表達式返回搜索模式的起點和終點(整數)。如果沒有發現匹配的值,將返回0。

    語法:

  1. regexp_instr(source_string,pattern[,position[,occurrence[,return_option[,match_parameter]]]])

    return_option:爲0時,返回第一個字符出現的位置,與instr作用相同。爲1時,返回所搜索字符出現以後下一個字符的位置。默認爲0。

    例1:

  1. select regexp_instr('MY INFO: Anxpp,23,and boy','[[:digit:]]') from users;

    該例會返回16。

    REGEXP_INSTR函數常常會被用到where子句中。

    2.3、REGEXP_LIKE

    通常使用REGEXP_LIKE進行模糊匹配。

    語法:

  1. regexp_like(source_string,pattern[match_parameter])

    比如,查找電話好嗎以666開頭的:

  1. select name from users where regexp_like(phone,'666');

    例1:

  1. select * from users where regexp_like('MY INFO: Anxpp,23,and boy','[[:digit:]]');

    此例判斷串中是否包含數字。

    該函數可以使用前面介紹的所有搜索功能作爲REGEXP_LIKE搜索的一部分,可以是非常複雜的搜索變得簡單。

    2.4、REPLACE和REGEXP_REPLACE

    REPLACE函數用於替換串中的某個值。

    語法:

  1. replace(char,search_string[,replace_string])

     如果不指定replace_string,會將搜索到的值刪除。

    輸入可以是任何字符數據類型:char,varchar2,nchar,nchar,nvarchar2,clob或nclob。

    例1:

  1. select replace('MY INFO: Anxpp,23,and boy','an') from users;

    返回:MY INFO: Anxpp,23,d boy

    下面演示使用該函數計算某字串在源串中出現的次數:

  1. select (length('MY INFO: Anxpp,23,and boy')-length(replace('MY INFO: Anxpp,23,and boy','an')))/length('an') from users;

    REGEXP_REPLACE是REPLACE的增強版,支持正則表達式,擴展了一些功能。

    語法:

  1. regexp_replace(source_string,pattern[,replace_string[,position[,occurrence[,match_parameter]]]])

    replace_string表示用什麼來替換source_string中與pattern匹配的部分。

    occurrence爲非負整數,0表示所有匹配項都被替換,爲正數時替換第n次匹配。

    其他參數在前面都已經介紹過了。

    例1:

    想象這樣一個場景:有一個分佈式的爬蟲,負責抓取網頁的程序已經將數據存入數據庫,而當前負責處理的程序需要從其中讀取其中的一些數據,包括電話號碼。號碼一般是11爲,前3位區號,中間4位表示交換機,再加上後面4位,格式也不能確定,我們可以試着用下面的SQL來讀取,生成我們想要的格式:

  1. select regexp_replace('電話:023 5868-8888 郵箱:[email protected]',
  2. '.*([[:digit:]]{3})([^[:digit:]]{0,2})([[:digit:]]{4})([^[:digit:]]{0,2})([[:digit:]]{4}).*',
  3. '(\1)\3\5'
  4. ) phone from users;

    該例返回:(023)58688888

    "\1"、“\3”、“\5”分別表示第1、3、5個數據集。其他的,大家慢慢看就能看懂了。

    配合where子句,可以限制要返回的行。

    2.5、REGEXP_COUNT

    REGEXP_COUNT函數返回在源串中出現的模式的次數,作爲對REGEXP_INSTR函數的補充。

    雖然COUNT是一個集合函數,操作的是行組,但是REGEXP_COUNT是單行函數,分別計算每一行。

    語法:

  1. regexp_count(source_char,pattern[,position[,match_param]])

    REGEXP_COUNT返回pattern在source_char串中出現的次數。如果未找到匹配,函數返回0。

    metch_param參數,相對於前面介紹的match_parameter參數多一個取值“x”。

    'x':忽略空格字符。默認情況下,空格與自身想匹配。

    metch_param如果指定了多個互相矛盾的值,將使用最後一個值。

    前面介紹了使用replace函數統計字串在源串中出現的次數,這裏可以使用REGEXP_COUNT實現,而且看起來更簡單:

  1. select regexp_count('MY INFO: Anxpp,23,and boy','an') from users;

    返回:1

    此處還是使用match_param參數進行不區分大小寫搜索:

  1. select regexp_count('MY INFO: Anxpp,23,and boy','an',1,'i') from users;

    返回:2


3、總結

    以上正則表達式相關函數的使用,主要體現在對正則表達式的掌握程度上,如果精通了正則表達式,一些非常複雜的串處理,也能用比較簡潔的代碼完成。

    更多閱讀:Oracle中的字符串類型及相關函數詳解


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章