jq - 用 startswith & endswith 過濾 JSON 資料

Posted on  Sep 12, 2022  in  Unix-like 命令列教學  by  Amo Chen  ‐ 2 min read

jq 是方便且成熟的 JSON 資料操作工具,可以幫助我們快速對 JSON 型態的資料進行擷取(extract)、過濾(filter)、運算(computing)甚至是重組(transform)等操作。

如果是常常需要與 JSON 格式資料打交道的開發者,可以投資一些時間好好熟悉 jq, 不過由於該工具提供各式各樣的功能,所以不免使用前要稍微查閱文件一番。

本文透過實際範例學習如何操作 jq 提供的 startswithendswith 函式進行資料篩選與過濾。

本文環境

  • jq 1.6

本文 JSON 範例資料

本文提供 2 種常用的 JSON 格式:

  • JSON Lines 檔案中的每 1 行都是 1 組 JSON 格式的資料
  • JSON array, 檔案中資料以 JSON 陣列的形式儲存,可以視為 1 個檔案就是 1 組 JSON 格式的資料。

JSON Lines 範例(本文將此範例檔命名為 example.jsonl ):

{"domain": "example.com", "hostname": "abc"}
{"domain": "example.com", "hostname": "def"}
{"domain": "example.com", "hostname": "abcdef"}

JSON array 範例(本文將此範例檔命名為 example

[
  {"domain": "example.com", "hostname": "abc"},
  {"domain": "example.com", "hostname": "def"},
  {"domain": "example.com", "hostname": "abcdef"}
]

startswith(str) + JSON Lines

如果想只過濾出 JSON lines 格式的資料,某個特定欄位是特定字串開頭的可使用以下指令:

$ jq -r '. | select(.<the field> | startswith("<the prefix>"))' example.jsonl

p.s. 請將 <the field><the prefix> 替換成所需要的值

例如下列指令過濾出 JSON Lines 資料中, hostnameabc 開頭的資料:

$ jq -r '. | select(.hostname | startswith("abc"))' example.jsonl

執行結果如下,可以看到 def 被排除:

{
  "domain": "example.com",
  "hostname": "abc"
}
{
  "domain": "example.com",
  "hostname": "abcdef"
}

如果只保持原本的 JSON Lines 格式,可以加上 -c / --compact-output :

$ jq -rc '. | select(.hostname | startswith("abc"))' example.jsonl

加上 -c 執行結果如下:

{"domain":"example.com","hostname":"abc"}
{"domain":"example.com","hostname":"abcdef"}

startswith(str) + JSON array

如果想只過濾出 JSON array 格式的資料,某個特定欄位是特定字串開頭的則可使用以下指令(可以看到指令與 JSON Lines 的過濾指令差了 .[] 的部分):

$ jq -r '.[] | select(.<the field> | startswith("<the prefix>"))' example

p.s. 請將 <the field><the prefix> 替換成所需要的值

例如下列指令過濾出 JSON array 資料中, hostnameabc 開頭的資料:

$ jq -r '.[] | select(.hostname | startswith("abc"))' example

執行結果如下,可以看到 def 被排除:

{
  "domain": "example.com",
  "hostname": "abc"
}
{
  "domain": "example.com",
  "hostname": "abcdef"
}

如果要維持 JSON array 的格式可以改為用 map(x) 函式進行過濾:

$ jq -r 'map(select(.hostname | startswith("abc")))' example

map(x) is equivalent to [.[] | x]

運用 map(x) 其實等同於 [.[] | x] 的寫法,以 'map(select(.hostname | startswith("abc")))' 為例的話,等同於:

[.[] | select(.hostname | startswith("abc"))]

endswith(str)

學會使用 startswith(str) 之後,想要過濾某個特定欄位是特定字串結尾的話,只要將前述指令中的 startswith 改為 endswith 即可,例如以下指令只過濾出 hostname 欄位是 def 結尾的資料:

$ jq -r 'map(select(.hostname | endswith("def")))' example
$ jq -rc '. | select(.hostname | endswith("def"))' example.jsonl

References

https://stedolan.github.io/jq/manual/

對抗久坐職業傷害

研究指出每天增加 2 小時坐著的時間,會增加大腸癌、心臟疾病、肺癌的風險,也造成肩頸、腰背疼痛等常見問題。

然而對抗這些問題,卻只需要工作時定期休息跟伸展身體即可!

你想輕鬆改變現狀嗎?試試看我們的 PomodoRoll 番茄鐘吧! PomodoRoll 番茄鐘會根據你所設定的專注時間,定期建議你 1 項辦公族適用的伸展運動,幫助你打敗久坐所帶來的傷害!

贊助我們的創作

看完這篇文章了嗎? 休息一下,喝杯咖啡吧!

如果你覺得 MyApollo 有讓你獲得實用的資訊,希望能看到更多的技術分享,邀請你贊助我們一杯咖啡,讓我們有更多的動力與精力繼續提供高品質的文章,感謝你的支持!