軌道
/
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中使用正規表示式,你必須提供第二個引數;使用空字串也可以。

以下範例將字串依任意空白分割。

"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 個練習,就能練習 正規表示式