跳转到内容

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 正则表达式

华夏公益教科书