Oracle正则表达式使⽤⽰例
正则表达式的基本例⼦
在使⽤这个新功能之前,您需要了解⼀些元字符的含义。句号 (.) 匹配⼀个正规表达式中的任意字符(除了换⾏符)。例如,正规表达式 a.b 匹配的字符串中⾸先包含字母 a,接着是其它任意单个字符(除了换⾏符),再接着是字母 b。字符串 axb、xaybx 和 abba 都与之匹配,因为在字符串中隐藏了这种模式。如果您想要精确地匹配以 a 开头和以 b 结尾的⼀条三个字母的字符串,则您必须对正规表达式进⾏定位。脱字符号 (^) 元字符指⽰⼀⾏的开始,⽽美元符号 ($) 指⽰⼀⾏的结尾(参见表1:附表见第4页)。因此,正则表达式 ^a.b$ 匹配字符串 aab、abb 或 axb。将这种⽅式与 LIKE 操作符提供的类似的模式匹配 a_b 相⽐较,其中 (_) 是单字符通配符。
默认情况下,⼀个正则表达式中的⼀个单独的字符或字符列表只匹配⼀次。为了指⽰在⼀个正则表达式中多次出现的⼀个字符,您可以使⽤⼀个量词,它也被称为重复操作符。.如果您想要得到从字母 a 开始并以字母 b 结束的匹配模式,则您的正则表达式看起来像这样:
^a.*b$。* 元字符重复前⾯的元字符 (.) 指⽰的匹配零次、⼀次或更多次。LIKE 操作符的等价的模式是 a%b,其中⽤百分号 (%) 来指⽰任意字符出现零次、⼀次或多次。
表 2 给出了重复操作符的完整列表。注意它包含了特殊的重复选项,它们实现了⽐现有的 LIKE 通配符更⼤的灵活性。如
果您⽤圆括号括住⼀个表达式,这将有效地创建⼀个可以重复⼀定次数的⼦表达式。例如,正则表达式 b(an)*a 匹配 ba、bana、banana、yourbananasplit 等。
Oracle 的正则表达式实施⽀持 POSIX (可移植操作系统接⼝)字符类,参见表 3 中列出的内容。这意味着您要查的字符类型可以⾮常特别。假设您要编写⼀条仅查⾮字母字符的 LIKE 条件 — 作为结果的 WHERE ⼦句可能不经意就会变得⾮常复杂。
POSIX 字符类必须包含在⼀个由⽅括号 ([]) 指⽰的字符列表中。例如,正则表达式 [[:lower:]] 匹配⼀个⼩写字母字符,⽽ [[:lower:]]{5} 匹配五个连续的⼩写字母字符。
除 POSIX 字符类之外,您可以将单独的字符放在⼀个字符列表中。例如,正则表达式 ^ab[cd]ef$ 匹配字符串 abcef 和 abdef。必须选择 c 或 d。
除脱字符 (^) 和连字符 (-) 之外,字符列表中的⼤多数元字符被认为是⽂字。正则表达式看起来很复杂,这是因为⼀些元字符具有随上下⽂环境⽽定的多重含义。^ 就是这样⼀种元字符。如果您⽤它作为⼀个字符列表的第⼀个字符,它代表⼀个字符列表的⾮。因此,[^[:digit:]]查包含了任意⾮数字字符的模式,⽽ ^[[:digit:]] 查以数字开始的匹配模式。连字符 (-) 指⽰⼀个范围,正规表达式 [a-m] 匹配字母 a 到字母 m 之间的任意字母。但如果它是⼀个字符⾏中的第⼀个字符(如在 [-afg] 中),则它就代表连字符。
之前的⼀个例⼦介绍了使⽤圆括号来创建⼀个⼦表达式;它们允许您通过输⼊更替元字符来输⼊可更替的选项,这些元字符由竖线 (|)分开。
例如,正则表达式 t(a|e|i)n 允许字母 t 和 n 之间的三种可能的字符更替。匹配模式包括如 tan、ten、tin 和 Pakistan 之类的字,但不包括 teen、mountain 或 tune。作为另⼀种选择,正则表达式 t(a|e|i)n 也可以表⽰为⼀个字符列表 t[aei]n。表 4 汇总了这些元字符。虽然存在更多的元字符,但这个简明的概述⾜够⽤来理解这篇⽂章使⽤的正则表达式。
REGEXP_LIKE 操作符
REGEXP_LIKE 操作符向您介绍在 Oracle 数据库中使⽤时的正则表达式功能。表 5 列出了 REGEXP_LIKE 的语法。
下⾯的 SQL 查询的 WHERE ⼦句显⽰了 REGEXP_LIKE 操作符,它在 ZIP 列中搜索满⾜正则表达式 [^[:digit:]] 的模式。它将检索ZIPCODE 表中的那些 ZIP 列值包含了任意⾮数字字符的⾏。
SELECT zip FROM zipcode WHERE REGEXP_LIKE(zip, '[^[:digit:]]')
ZIP
-----
ab123
123xy
007ab
abcxy
这个正则表达式的例⼦仅由元字符组成,更具体来讲是被冒号和⽅括号分隔的 POSIX 字符类 digit。第⼆组⽅括号(如 [^[:digit:]] 中所⽰)包括了⼀个字符类列表。如前⽂所述,需要这样做是因为您只可以将 POSIX 字符类⽤于构建⼀个字符列表。
REGEXP_INSTR 函数
这个函数返回⼀个模式的起始位置,因此它的功能⾮常类似于 INSTR 函数。新的 REGEXP_INSTR 函数的语法在表 6 中给出。这两个函数之间的主要区别是,REGEXP_INSTR 让您指定⼀种模式,⽽不是⼀个特定的搜索字符串;因⽽它提供了更多的功能。接下来的⽰例使⽤ REGEXP_INSTR 来返回字符串 Joe Smith, 10045 Berry Lane, San Joseph, CA 91234 中的五位模式的起始位置。如果正则表达式被写为 [[:digit:]]{5},则您将得到门牌号的起始位置⽽不是的,因为 10045 是第⼀次出现五个连续数字。因此,您必须将表达式定位到该⾏的末尾,正如 $ 元字符所⽰,该函数将显⽰的起始位置,⽽不管门牌号的数字个数。
SELECT REGEXP_INSTR('Joe Smith, 10045 Berry Lane, San Joseph, CA 91234',
'[[:digit:]]{5}$') AS rx_instr FROM dual
RX_INSTR
----------
45
编写更复杂的模式
让我们在前⼀个例⼦的模式上展开,以便包含⼀个可选的四位数字模式。您的模式现在可能看起来像这样:[[:digit:]]{5} (-[[:digit:]]{4})?$。如果您的源字符串以 5 位或 5 位 + 4 位的格式结束,则您将能够显⽰该模式的起始位置。
SELECT REGEXP_INSTR('Joe Smith, 10045 Berry Lane, San Joseph, CA 91234-1234',
' [[:digit:]]{5}(-[[:digit:]]{4})?$') AS starts_at FROM dual
STARTS_AT
----------
44
在这个⽰例中,括弧⾥的⼦表达式 (-[[:digit:]]{4}) 将按 ? 重复操作符的指⽰重复零次或⼀次。此外,企图⽤传统的 SQL 函数来实现相同的结果甚⾄对 SQL 专家也是⼀个挑战。为了更好地说明这个正规表达式⽰例的不同组成部分,表 7 包含了⼀个对单个⽂字和元字符的描述。
REGEXP_SUBSTR 函数
类似于 SUBSTR 函数的 REGEXP_SUBSTR 函数⽤来提取⼀个字符串的⼀部分。表 8 显⽰了这个新函数的语法。在下⾯的⽰例中,匹配模式 [^,]* 的字符串将被返回。该正则表达式搜索其后紧跟着空格的⼀个逗号;然后按 [^,]* 的指⽰搜索零个或更多个不是逗号的字符,最后查另⼀个逗号。这种模式看起来有点像⼀个⽤逗号分隔的值字符串。
SELECT REGEXP_SUBSTR('first field, second field , third field', ', [^,]*,') FROM dual
REGEXP_SUBSTR('FIR
------------------
, second field ,
REGEXP_REPLACE 函数
让我们⾸先看⼀下传统的 REPLACE SQL 函数,它把⼀个字符串⽤另⼀个字符串来替换。假设您的数据在正⽂中有不必要的空格,您希望⽤单个空格来替换它们。利⽤ REPLACE 函数,您需要准确地列出您要替换多少个空格。然⽽,多余空格的数⽬在正⽂的各处可能不是相同的。下⾯的⽰例在 Joe 和 Smith 之间有三个空格。REPLACE 函数的参数指定要⽤⼀个空格来替换两个空格。在这种情况下,结果在原来的字符串的 Joe 和 Smith 之间留下了⼀个额外的空格。
SELECT REPLACE('Joe Smith',' ', ' ') AS replace FROM dual
REPLACE
---------
Joe Smith
REGEXP_REPLACE 函数把替换功能向前推进了⼀步,其语法在表 9 中列出。以下查询⽤单个空格替换了任意两个或更多的空格。( )⼦表达式包含了单个空格,它可以按 {2,} 的指⽰重复两次或更多次。
SELECT REGEXP_REPLACE('Joe Smith', '( ){2,}', ' ') AS RX_REPLACE FROM dual
RX_REPLACE
----------
Joe Smith
后向引⽤ 正则表达式的⼀个有⽤的特性是能够存储⼦表达式供以后重⽤;这也被称为后向引⽤(在表 10 中对其进⾏了概述)。它允许复杂的替换功能,如在新的位置上交换模式或显⽰重复出现的单词或字母。⼦表达式的匹配部分保存在临时缓冲区中。缓冲区从左⾄右进⾏编号,并利⽤ \digit 符号进⾏访问,其中 digit 是 1 到 9 之间的⼀个数字,它匹配第 digit 个⼦表达式,⼦表达式⽤⼀组圆括号来显⽰。
接下来的例⼦显⽰了通过按编号引⽤各个⼦表达式将姓名 Ellen Hildi Smith 转变为 Smith, Ellen Hildi。
SELECT REGEXP_REPLACE(
'Ellen Hildi Smith',
'(.*) (.*) (.*)', '\3, \1 \2')
FROM dual
REGEXP_REPLACE('EL
------------------
Smith, Ellen Hildi
该 SQL 语句显⽰了⽤圆括号括住的三个单独的⼦表达式。每⼀个单独的⼦表达式包含⼀个匹配元字符 (.),并紧跟着 * 元字符,表⽰任
何字符(除换⾏符之外)都必须匹配零次或更多次。空格将各个⼦表达式分开,空格也必须匹配。圆括号创建获取值的⼦表达式,并且可以⽤ \digit 来引⽤。第⼀个⼦表达式被赋值为 \1 ,第⼆个 \2,以此类推。这些后向引⽤被⽤在这个函数的最后⼀个参数 (\3, \1 \2) 中,这个函数有效地返回了替换⼦字符串,并按期望的格式来排列它们(包括逗号和空格)。表 11 详细说明了该正则表达式的各个组成部分。
后向引⽤对替换、格式化和代替值⾮常有⽤,并且您可以⽤它们来查相邻出现的值。接下来的例⼦显⽰了使⽤ REGEP_SUBSTR 函数来查任意被空格隔开的重复出现的字母数字值。显⽰的结果给出了识别重复出现的单词 is 的⼦字符串。
SELECT REGEXP_SUBSTR(
'The final test is is the implementation',
'([[:alnum:]]+)([[:space:]]+)\1') AS substr
FROM dual
SUBSTR
------
is is
匹配参数选项
您可能已经注意到了正则表达式操作符和函数包含⼀个可选的匹配参数。这个参数控制是否区分⼤⼩写、换⾏符的匹配和保留多⾏输⼊。
正则表达式的实际应⽤
您不仅可以在队列中使⽤正则表达式,还可以在使⽤ SQL 操作符或函数的任何地⽅(⽐如说在 PL/SQL 语⾔中)使⽤正则表达式。您可以编写利⽤正则表达式功能的触发器,以验证、⽣成或提取值。
接下来的例⼦演⽰了您如何能够在⼀次列检查约束条件中应⽤ REGEXP_LIKE 操作符来进⾏数据验证。它在插⼊或更新时检验正确的社会保险号码格式。如 123-45-6789 和 123456789 之类格式的社会保险号码对于这种列约束条件是可接受的值。有效的数据必须以三个数字开始,紧跟着⼀个连字符,再加两个数字和⼀个连字符,最后⼜是四个数字。另⼀种表达式只允许 9 个连续的数字。竖线符号 (|) 将各个选项分开。
ALTER TABLE students
ADD CONSTRAINT stud_ssn_ck CHECK
(REGEXP_LIKE(ssn,
'^([[:digit:]]{3}-[[:digit:]]{2}-[[:digit:]]{4}|[[:digit:]]{9})$'))
由 ^ 和 $ 指⽰的开头或结尾的字符都是不可接受的。确保您的正则表达式没有分成多⾏或包含任何不必要的空格,除⾮您希望格式如此并相应地进⾏匹配。表 12 说明了该正则表达式⽰例的各个组成部分。
将正则表达式与现有的功能进⾏⽐较
正则表达式有⼏个优点优于常见的 LIKE 操作符和 INSTR、SUBSTR 及 REPLACE 函数的。这些传统的 SQL 函数不便于进⾏模式匹配。只有 LIKE 操作符通过使⽤ % 和 _ 字符匹配,但 LIKE 不⽀持表达式的重复、复杂的更替、字符范围、字符列表和 POSIX 字符类等等。此外,新的正则表达式函数允许检测重复出现的单词和模式交换。这⾥的例⼦为您提供了正则表达式领域的⼀个概览,以及您如何能够在您的应⽤程序中使⽤它们。
附表见下页:
表 1:定位元字符
元字符说明
^使表达式定位⾄⼀⾏的开头
$使表达式定位⾄⼀⾏的末尾
表 2:量词或重复操作符
量词说明
*匹配 0 次或更多次
匹配 0 次或 1 次
+匹配 1 次或更多次
{m}正好匹配m次
{m,}⾄少匹配m次{m, n}⾄少匹配m次但不超过n次
表 3:预定义的 POSIX 字符类
字符类说明
[:alpha:]字母字符
[:lower:]⼩写字母字符
[:upper:]⼤写字母字符
[:digit:]数字
[:alnum:]字母数字字符
[:space:]空⽩字符(禁⽌打印),如回车符、换⾏符、竖直制表符和换页符
[:punct:]标点字符
[:cntrl:]控制字符(禁⽌打印)
[:print:]可打印字符
表 4:表达式的替换匹配和分组
元字符说明
|替换分隔替换选项,通常与分组操作符 () ⼀起使⽤
( )分组将⼦表达式分组为⼀个替换单元、量词单元或后向引⽤单元(参见“”部分)[char]字符列表表⽰⼀个字符列表;⼀个字符列表中的⼤多数元字符(除字符类、^ 和 - 元字符之外)被理解为⽂字
表 5:REGEXP_LIKE 操作符
语法说明
REGEXP_LIKE(source_string, pattern
[, match_parameter])source_string ⽀持字符数据类型(CHAR、VARCHAR2、CLOB、NCHAR、NVARCHAR2 和 NCLOB,但不包括 LONG)。pattern 参数是正则表达式的另⼀个名称。match_parameter 允许可选的参数(如处理换⾏符、保留多⾏格式化以及提供对区分⼤⼩写的控制)。
表 6:REGEXP_INSTR 函数
语法说明REGEXP_INSTR(source_string,
pattern
[, start_position
[, occurrence
[, return_option
[, match_parameter]]]])该函数查 pattern ,并返回该模式的第⼀个位置。您可以随意指定您想要开始搜索的 start_position。 occurrence 参数默认为 1,除⾮您指定您要查接下来出现的⼀个模式。return_option 的默认值为 0,它返回该模式的起始位置;值为 1 则返回符合匹配条件的下⼀个字符的起始位置。
表 7: 5 位数字加 4 位表达式的说明
语法说明
必须匹配的空⽩
[:digit:]POSIX 数字类
]字符列表的结尾
{5}字符列表正好重复出现 5 次
(⼦表达式的开头
-⼀个⽂字连字符,因为它不是⼀个字符列表内的范围元字符
[字符列表的开头
[:digit:]POSIX [:digit:]类
[字符列表的开头]字符列表的结尾{4}字符列表正好重复出现 4 次)结束圆括号,结束⼦表达式?? 量词匹配分组的⼦表达式 0 或 1 次,从⽽使得 4 位代码可选$定位元字符,指⽰⾏尾
表 8:REGEXP_SUBSTR 函数
语法说明
REGEXP_SUBSTR(source_string, pattern
[, position [, occurrence
[, match_parameter]]])
REGEXP_SUBSTR 函数返回匹配模式的⼦字符串。
表 9: REGEXP_REPLACE 函数
语法说明
REGEXP_REPLACE(source_string, pattern
[, replace_string [, position
[,occurrence, [match_parameter]]]])
该函数⽤⼀个指定的 replace_string 来替换匹配的模式,从⽽允许复杂的“搜索并替换”操作。
表 10:后向引⽤元字符
元字符说明
\digit反斜线紧跟着⼀个 1 到 9 之间的数字,反斜线匹配之前的⽤括号括起来的第 digit 个⼦表达式。
(注意:反斜线在正则表达式中有另⼀种意义,取决于上下⽂,它还可能表⽰ Escape 字符。
表 11:模式交换正则表达式的说明
正则表达式项⽬说明
(第⼀个⼦表达式的开头
.匹配除换⾏符之外的任意单字符
*重复操作符,匹配之前的 . 元字符 0 到n 次
)第⼀个⼦表达式的结尾;匹配结果在 \1
中获取(在这个例⼦中,结果为 Ellen。)必须存在的空⽩(第⼆个⼦表达式的开头.匹配除换⾏符之外的任意单个字符*重复操作符,匹配之前的 . 元字符 0 到n 次)第⼆个⼦表达式的结尾;匹配结果在 \2
中获取(在这个例⼦中,结果为 Hildi。)空⽩(第三个⼦表达式的开头.匹配除换⾏符之外的任意单字符*重复操作符,匹配之前的 . 元字符 0 到n 次)第三个⼦表达式的结尾;匹配结果在 \3
中获取(在这个例⼦中,结果为 Smith。)
表 12:社会保险号码正则表达式的说明
正则匹配指定字符串以后的内容
正则表达式项⽬
^
(
[
[:digit:]
]
{3}
-
[
[:digit:]
]
{2}
-
[
[:digit:]
]
{4}
|
[
[:digit:]
]
{9}
)
$
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论