跳轉到內容

XQuery/正則表示式

來自華夏公益教科書,開放的書籍,開放的世界

您想測試文字是否與特定字元模式匹配。您想將文字模式替換為其他模式。您的文字具有重複模式,您希望將其分解為離散專案。

為了解決上述三個問題,XQuery 提供以下函式

  • matches($input, $regex) - 如果輸入包含正則表示式,則返回 true
  • replace($input, $regex, $string) - 將與正則表示式匹配的輸入字串替換為新字串
  • tokenize($input, $regex) - 返回與正則表示式匹配的專案序列

透過這些函式,我們可以訪問強大的正則表示式語法。

正則表示式概述

[編輯 | 編輯原始碼]

正則表示式 (“regex”) 是一門獨立的學科。如果您希望充分利用這種用模式描述字串的方式,您應該參考單獨的介紹。Priscilla Walmsley 的《XQuery》(第 18 章)對提供的功能進行了清晰的總結。

  • fn:matches($input, $regex, $flags) 以字串和正則表示式作為輸入。如果正則表示式與字串的任何部分匹配,則該函式返回 true。如果它不匹配,則返回 false。如果您只想在模式與整個字串匹配時該函式返回 true,請用錨點(開頭為 ^,結尾為 $)將字串括起來。請注意,這與 XML 模式不同,在 XML 模式中 ^ 和 $ 是隱含的。
  • fn:replace($input, $regex, $string, $flags) 以字串、正則表示式和替換字串作為輸入。它返回一個新字串,該字串是將輸入字串中所有與模式匹配的部分替換為替換字串後的字串。您可以使用 $1 到 $99 將用括號捕獲的字元組重新插入替換字串中。
  • fn:tokenize($input, $regex, $flags) 返回一個字串陣列,該陣列包含輸入字串中所有模式匹配之間所有子字串。該陣列不會包含匹配項本身。

在正則表示式中,大多數字符代表自身,因此您不必使用特殊的正則表示式語法來使用這三個函式。在正則表示式中,點 (.) 代表除換行符之外的所有字元。緊跟在字元或表示式(如點)之後,可以新增一個量詞,它告訴應該重複該字元多少次:“*” 代表“0、1 或多次”,“?” 代表“0 或 1 次”,而“+” 代表“1 或多次”。組合 “*?” 替換與模式匹配的最短子字串。注意:這僅僅是正則表示式主題的表面!

這三個函式都接受可選的標誌引數來設定匹配模式。以下四個標誌可用

  • i 使正則表示式匹配不區分大小寫。
  • s 啟用“單行模式”或“點全部”模式。在此模式下,點匹配每個字元,包括換行符,因此字串被視為單行。
  • m 啟用“多行模式”。在此模式下,錨點 "^" 和 "$" 除了應用於整個字串之外,還在字串中的換行符之前和之後匹配。
  • x 啟用“自由空格模式”。在此模式下,正則表示式模式中的空格將被忽略。這主要用於將複雜正則表示式拆分為多行,但又不打算匹配換行符時。

如果未使用標誌,則可以只保留插槽為空或寫成 ""。

matches() 示例

[編輯 | 編輯原始碼]
let $input := 'Hello World'
return
<result>{
  (matches($input, 'Hello World') =  true(),
   matches($input, 'Hi') =  false(),
   matches($input, 'H.*') = true(),
   matches($input, 'H.*o W.*d') =  true(),
   matches($input, 'Hel+o? W.+d') = true(),
   matches($input, 'Hel?o+') = false(),
   matches($input, 'hello', "i") = true(), 
   matches($input, 'he l lo', "ix") = true() ,
   matches($input, '^Hello$') = false(), 
   matches($input, '^Hello') = true()
    )}
</result>

執行

tokenize() 示例

[編輯 | 編輯原始碼]
<result>{
(let $input := 'red,orange,yellow,green,blue'
return deep-equal( tokenize($input, ',') , ('red','orange','yellow','green','blue'))
 ,
let $input := 'red,
orange,	     yellow,  green,blue'
return  deep-equal(tokenize($input, ',\s*') , ('red','orange','yellow','green','blue'))
,
let $input := 'red   ,
orange  ,	     yellow    ,  green ,  blue'
return  not(deep-equal(tokenize($input, ',\s*') , ('red','orange','yellow','green','blue')))
,
let $input := 'red   ,
orange  ,	     yellow    ,  green ,  blue'
return  deep-equal(tokenize($input, '\s*,\s*') , ('red','orange','yellow','green','blue'))
)
}</result>

在第二個示例中,“\s” 代表一個空格字元,因此與“orange”之前的換行符和“yellow”之前的製表符匹配。它被量詞 "*" 限定,因此該模式會刪除逗號後的空格,但不會刪除逗號前的空格。要刪除所有空格,請使用模式 '\s*,\s*'。

執行

replace() 示例

[編輯 | 編輯原始碼]
<result>{
( 
let $input := 'red,orange,yellow,green,blue'
return ( replace($input, ',', '-') = 'red-orange-yellow-green-blue' )
,
let $input := 'Hello World'
return (
    replace($input, 'o', 'O') = "HellO WOrld" ,
    replace($input, '.', 'X') = "XXXXXXXXXXX" ,
    replace($input, 'H.*?o', 'Bye') = "Bye World" 
    )
,
let $input := 'HellO WOrld'
return ( replace($input, 'o', 'O', "i") = "HellO WOrld" )
,
let $input := 'Chapter 1 … Chapter 2 …'
  return ( replace($input, "Chapter (\d)", "Section $1.0")  =  "Section 1.0 … Section 2.0 …")
)
}</result>

在最後一個示例中,“\d” 代表任何數字;圍繞 “\d” 的括號將變數 “$1” 繫結到它匹配的任何數字;在替換字串中,此變數將被匹配的數字替換。

執行

更大型的示例

[編輯 | 編輯原始碼]

參考文獻

[編輯 | 編輯原始碼]

正則表示式庫包含 2,600 多個正則表示式示例:正則表示式庫

此頁面對正則表示式模式進行了非常有用的總結:正則表示式備忘單

此頁面描述瞭如何在 XQuery 和 XPath 中使用正則表示式:XQuery 和 XPath 正則表示式

華夏公益教科書