当前位置:  首页>> 技术小册>> Julia入门教程

正则表达式(regular expression)描述了一种字符串匹配的模式,可以用来检查一个串是否含有某种子串、将匹配的子串做替换或者从某个串中取出符合某个条件的子串等。

Julia 具有与 Perl 兼容的正则表达式 (regexes)。

Julia 的正则表达式的三种形式,分别是匹配,替换和转化:

  1. 匹配:m//(还可以简写为//,略去m)
  2. 替换:s///
  3. 转化:tr///

这三种形式一般都和 =~ 或 !~ 搭配使用, =~ 表示相匹配,!~ 表示不匹配。

Julia 中正则表达式的输入使用了前缀各类以 r 开头:

实例

  1. julia> re = r"^\s*(?:#|$)"
  2. r"^\s*(?:#|$)"
  3. julia> typeof(re)

Regex

若要检查正则表达式是否匹配某字符串,就用 occursin:

实例

  1. julia> occursin(r"^\s*(?:#|$)", "not a comment")
  2. false
  3. julia> occursin(r"^\s*(?:#|$)", "# a comment")
  4. true

可以看到,occursin 只返回正确或错误,表明给定正则表达式是否在该字符串中出现。然而,通常我们不只想知道字符串是否匹配,更想了解它是如何匹配的。要捕获匹配的信息,可以改用 match 函数:

实例

  1. julia> match(r"^\s*(?:#|$)", "not a comment")
  2. julia> match(r"^\s*(?:#|$)", "# a comment")
  3. RegexMatch("#")

若正则表达式与给定字符串不匹配,match 返回 nothing——在交互式提示框中不打印任何东西的特殊值。除了不打印,它是一个完全正常的值,这可以用程序来测试:

实例

  1. m = match(r"^\s*(?:#|$)", line)
  2. if m === nothing
  3. println("not a comment")
  4. else
  5. println("blank or comment")
  6. end

如果正则表达式匹配,match 的返回值是一个 RegexMatch 对象。这些对象记录了表达式是如何匹配的,包括该模式匹配的子字符串和任何可能被捕获的子字符串。上面的例子仅仅捕获了匹配的部分子字符串,但也许我们想要捕获的是注释字符后面的任何非空文本。我们可以这样做:

实例

  1. julia> m = match(r"^\s*(?:#\s*(.*?)\s*$|$)", "# a comment ")
  2. RegexMatch("# a comment ", 1="a comment")

当调用 match 时,你可以选择指定开始搜索的索引。例如:

实例

  1. julia> m = match(r"[0-9]","aaaa1aaaa2aaaa3",1)
  2. RegexMatch("1")
  3. julia> m = match(r"[0-9]","aaaa1aaaa2aaaa3",6)
  4. RegexMatch("2")
  5. julia> m = match(r"[0-9]","aaaa1aaaa2aaaa3",11)
  6. RegexMatch("3")

你可以从 RegexMatch 对象中提取如下信息:

匹配的整个子字符串:m.match
作为字符串数组捕获的子字符串:m.captures
整个匹配开始处的偏移:m.offset
作为向量的捕获子字符串的偏移:m.offsets
当捕获不匹配时,m.captures 在该处不再包含一个子字符串,而是 什么也不 包含;此外,m.offsets 的偏移量为 0(回想一下,Julia 的索引是从 1 开始的,因此字符串的零偏移是无效的)。下面是两个有些牵强的例子:

实例

  1. julia> m = match(r"(a|b)(c)?(d)", "acd")
  2. RegexMatch("acd", 1="a", 2="c", 3="d")
  3. julia> m.match
  4. "acd"
  5. julia> m.captures
  6. 3-element Vector{Union{Nothing, SubString{String}}}:
  7. "a"
  8. "c"
  9. "d"
  10. julia> m.offset
  11. 1
  12. julia> m.offsets
  13. 3-element Vector{Int64}:
  14. 1
  15. 2
  16. 3
  17. julia> m = match(r"(a|b)(c)?(d)", "ad")
  18. RegexMatch("ad", 1="a", 2=nothing, 3="d")
  19. julia> m.match
  20. "ad"
  21. julia> m.captures
  22. 3-element Vector{Union{Nothing, SubString{String}}}:
  23. "a"
  24. nothing
  25. "d"
  26. julia> m.offset
  27. 1
  28. julia> m.offsets
  29. 3-element Vector{Int64}:
  30. 1
  31. 0
  32. 2

让捕获作为数组返回是很方便的,这样就可以用解构语法把它们和局域变量绑定起来。为了方便,RegexMatch 对象实现了传递到 captures 字段的迭代器方法,因此您可以直接解构匹配对象:

实例

  1. julia> first, second, third = m; first
  2. "a"

通过使用捕获组的编号或名称对 RegexMatch 对象进行索引,也可实现对捕获的访问:

实例

  1. julia> m=match(r"(?<hour>\d+):(?<minute>\d+)","12:45")
  2. RegexMatch("12:45", hour="12", minute="45")
  3. julia> m[:minute]
  4. "45"
  5. julia> m[2]
  6. "45"

使用 replace 时利用 \n 引用第 n 个捕获组和给替换字符串加上 s 的前缀,可以实现替换字符串中对捕获的引用。捕获组 0 指的是整个匹配对象。可在替换中用 \g 对命名捕获组进行引用。例如:

  1. julia> replace("first second", r"(\w+) (?<agroup>\w+)" => s"\g<agroup> \1")
  2. "second first"

为明确起见,编号捕获组也可用 \g 进行引用,例如:

  1. julia> replace("a", r"." => s"\g<0>1")
  2. "a1"

你可以在后双引号的后面加上 i, m, s 和 x 等标志对正则表达式进行修改。


该分类下的相关小册推荐:

暂无相关推荐.