学习路径
/
jq
jq
/
教学大纲
/
正则表达式
正则

正则表达式 属于 jq

1 个练习

关于 正则表达式

正则表达式(regex)是用于指定文本搜索模式的字符序列。

学习正则表达式的语法超出了本主题的范围。我们将重点介绍jq提供的、用于使用正则表达式的那些表达式。

正则表达式的风格

不同的工具实现了不同版本的正则表达式。jq内置了 Oniguruma 正则表达式库,它与 Perl v5.8 的正则表达式基本兼容。

jq使用的具体语法可以在 Oniguruma 的 GitHub 仓库中找到。

Caution

jq没有为正则表达式提供任何特殊语法。它们只是以字符串的形式表示。这意味着正则表达式中的任何反斜杠都需要在字符串中转义。

例如,数字字符类(\d)必须写成"\\d"。

正则表达式函数

jq中的正则表达式仅限于一组过滤器。

简单匹配

当你需要知道一个字符串是否匹配某个模式时,使用test过滤器。

STRING | test(REGEX)
STRING | test(REGEX; FLAGS)
STRING | test([REGEX, FLAGS])

这个过滤器会输出一个_布尔_结果。

"Hello World!" | test("W")    # => true
"Goodbye Mars" | test("W")    # => false

关于匹配的信息

当你需要提取真正匹配该模式的子字符串时,使用match过滤器。

STRING | match(REGEX)
STRING | match(REGEX; FLAGS)
STRING | match([REGEX, FLAGS])

这个过滤器会输出:

  • 如果没有匹配,则什么都不输出,或
  • 如果存在匹配,则输出一个包含各种属性的对象。

这个例子使用反向引用语法\1,查找两个相同的连续元音。

"Hello World!" | match("([aeiou])\\1")
# => empty

"Goodbye Mars" | match("([aeiou])\\1")
# => {
#      "offset": 1,
#      "length": 2,
#      "string": "oo",
#      "captures": [
#        {
#          "offset": 1,
#          "length": 1,
#          "string": "o",
#          "name": null
#        }
#      ]
#    }

match过滤器会为_每个_匹配返回一个对象。这个例子演示了"g"标志如何用来查找所有元音。

"Goodbye Mars" | match("[aeiou]"; "g")
# => { "offset": 1, "length": 1, "string": "o", "captures": [] }
#    { "offset": 2, "length": 1, "string": "o", "captures": [] }
#    { "offset": 6, "length": 1, "string": "e", "captures": [] }
#    { "offset": 9, "length": 1, "string": "a", "captures": [] }

捕获的子字符串

与match过滤器类似,capture过滤器在有匹配时会返回一个对象。

STRING | capture(REGEX)
STRING | capture(REGEX; FLAGS)
STRING | capture([REGEX, FLAGS])

返回的对象是命名捕获的映射。

"JIRAISSUE-1234" | capture("(?<project>\\w+)-(?<issue_num>\\d+)")
# => {
#      "project": "JIRAISSUE",
#      "issue_num": "1234"
#    }

只取子字符串

scan过滤器类似于带"g"标志的match。

STRING | scan(REGEX)
STRING | scan(REGEX; FLAGS)

# note, there is no scan([REGEX, FLAGS]) version, unlike other filters

scan会输出一个_子字符串流_。

"Goodbye Mars" | scan("[aeiou]")
# => "o"
#    "o"
#    "e"
#    "a"

使用[...]数组构造器来捕获这些子字符串。

"Goodbye Mars" | [ scan("[aeiou]") ]
# => ["o", "o", "e", "a"]

拆分字符串

如果你知道字符串中想要保留的部分,就用match或scan。如果你知道想要丢弃的部分,就用split。

STRING | split(REGEX; FLAGS)
Caution

单参数的split过滤器会把它的实参当作固定字符串处理。

要在split中使用正则表达式,你必须提供第 2 个实参;使用空字符串也是可以的。

下面这个例子按任意空白字符拆分字符串。

"first   second           third fourth" | split("\\s+"; "")
# => ["first", "second", "third", "fourth"]
Note

如果我们忘了标志参数,就会得到这样的结果。

"first   second           third fourth" | split("\\s+")
# => ["first   second           third fourth"]

只有一个结果:输入中并没有出现_固定字符串_\s+。

单参数的split无法处理_任意_空白字符。按空格拆分则会得到这样的结果。

"first   second           third fourth" | split(" ")
# => ["first", "", "", "second", "", "", "", "",
#     "", "", "", "", "", "", "third", "fourth" ]

替换

sub和gsub过滤器可以转换输入字符串,把输入中匹配到的部分替换为替换字符串。

只替换第一个匹配项,就用sub。 替换所有匹配项,就用gsub。

STRING | sub(REGEX; REPLACEMENT)
STRING | sub(REGEX; REPLACEMENT; FLAGS)
STRING | gsub(REGEX; REPLACEMENT)
STRING | gsub(REGEX; REPLACEMENT; FLAGS)
"Goodnight kittens. Goodnight mittens." | sub("night"; " morning")
# => "Good morning kittens. Goodnight mittens."

"Goodnight kittens. Goodnight mittens." | gsub("night"; " morning")
# => "Good morning kittens. Good morning mittens."

替换文本可以引用匹配到的子字符串;使用命名捕获和字符串插值。

"Some 3-letter acronyms: gnu, csv, png"
| gsub( "\\b(?<tla>[[:alpha:]]{3})\\b";     # find words 3 letters long
        "\(.tla | ascii_upcase)" )          # upper-case the match
# => "Some 3-letter acronyms: GNU, CSV, PNG"

标志

在上面所有的过滤器中,FLAGS 是一个由零个或多个受支持的标志组成的字符串。

  • g - 全局搜索(查找所有匹配项,而不只是第一个)
  • i - 不区分大小写的搜索
  • m - 多行模式('.' 会匹配换行符)
  • n - 忽略空匹配
  • p - 同时启用 s 和 m 模式
  • s - 单行模式('^' -> '\A','$' -> '\Z')
  • l - 查找尽可能长的匹配
  • x - 扩展正则表达式格式(忽略空白和注释)

例如

"JIRAISSUE-1234" | capture("(?<project>\\w+)-(?<issue_num>\\d+)")

# or with Extended formatting

"JIRAISSUE-1234" | capture("
                     (?<project>   \\w+ )  # the Jira project
                     -                     # followed by a hyphen
                     (?<issue_num> \\d+ )  # followed by digits
                   "; "x")
通过 GitHub 编辑 该链接会在新窗口或标签页中打开

学习 正则表达式

练习已锁定

再解锁 1 个练习即可练习 正则表达式