iT邦幫忙

2024 iThome 鐵人賽

DAY 21
0
AI/ ML & Data

使用 jq 處理資料系列 第 21

Day21: jq slurp

  • 分享至 

  • xImage
  •  

昨天我們認識了 jq 的變數,應用在方向的顯示資訊對應上,比起使用 if-then-else-end,使用變數對應取值是更俐落的做法。只是,方向的資料雖然不多、卻也不短,直接把 json 放在主程式內,還是嫌稍長了。我們今天就來看看,jq 的 slurp 可以怎麼幫上忙吧。

對話中學習

徒弟:把整個 $direction 的 json 寫在程式中看起來太冗長了,有沒有存在一個 direction.json 檔案中的辦法?

師傅:很好的問題。我們今天就來學習如何從外部文件讀取多個 JSON 資料。

徒弟:太好了!這樣可以讓程式更整潔吧?

師傅:沒錯。首先,我們要了解 jq 的 -s--slurp 選項。

徒弟:這是什麼意思呢,師傅?

師傅-s 選項將多個輸入合併為一個陣列。它讀取整個輸入串流,並將其作為單個陣列傳遞給 jq。

徒弟:哦,這聽起來很有用。可以舉個例子嗎?

師傅:當然。看這個:

jq -s '.' file1.json file2.json

師傅:這會將 file1.json 和 file2.json 的內容合併為一個陣列。

徒弟:我明白了。那麼,我們如何用這個來讀取 direction.json 呢?

師傅:首先,我們準備好 direction.json 文件。內容如下:

{
  "N": "北 ↑", "S": "南 ↓", "E": "東 →", "W": "西 ←",
  "NE": "東北 ↗", "SE": "東南 ↘", "SW": "西南 ↙", "NW": "西北 ↖"
}

徒弟:好的,我已經建立了這個文件。接下來呢?

師傅:現在,我們使用 jq 讀取這個文件並將其儲存為變數。

jq -s '.[0] as $direction | $direction' direction.json

徒弟:這行命令看起來有點複雜,能解釋一下嗎?

師傅:當然。-s 選項將文件內容讀取為陣列,.[0] 取第一個元素,然後我們將其賦值給 $direction 變數。

徒弟:明白了。那麼,接著作法就跟先前一樣 $direction[.movingDirection] 對嗎?

師傅:沒錯。使用 slurp 就可以讓資料存在獨立的 json 檔案,不用全部寫在 jq 程式中了,提高了可維護姓。

徒弟:謝謝師傅。我會好好練習這個技巧的。

jq -s (slurp)

-s--slurp 選項用於將多個輸入視為單個大陣列。它會讀取整個輸入串流,並將其作為一個陣列傳遞給 jq 程式。這在處理多個 JSON 對象或需要將多個輸入合併為一個陣列時非常有用。

我們先將山陀兒颱風的資料下載為 typhoon1005.json,如下:

curl -s https://opendata.cwa.gov.tw/api/v1/rest/datastore/W-C0034-005?Authorization=%AUTHORIZATION% > typhoon1005.json

再如對話中所說,準備 direction.json,這樣我們就有兩個 json 檔案。接著,使用 jq -s 讀取 direction.json 和 typhoon1005.json。我們已經知道讀取的結果是一個大的陣列,而陣列的第一個元素會是 direction.json 的內容,第二個元素則會是 typhoon1005.json 的內容。

因此我們可以如下方式,命名陣列的第一個元素為 $direction,第二個元素為 $ty。

jq -s ".[0] as $direction | .[1] as $ty | $direction[\"N\"], ($ty | .records.tropicalCyclones.tropicalCyclone[] | .typhoonName)" direction.json typhoon1005.json

執行此指令的結果是:

"北 ↑"
"KRATHON"

由此可知,只要應用 $direction 和 $ty 這兩個變數,就可以套用先前的程式碼了 🎉

按照這個做法,修改昨天的程式碼如下,跑起來的結果會跟昨天一樣:

jq -c -r -s ".[0] as $direction | .[1] as $ty |[\"時間     \",\"經度\",\"緯度\",\"氣壓\",\"風速MAX\",\"陣風MAX\",\"方向 \",\"預測\"],[$ty.records.tropicalCyclones.tropicalCyclone[] | select(.typhoonName==\"KRATHON\") | .analysisData.fix[-5:][] | [.fixTime[0:13], (.coordinate|split(\",\")[0]), (.coordinate|split(\",\")[1]), .pressure, .maxWindSpeed, .maxGustSpeed, $direction[.movingDirection], .movingPrediction[0].value]][] | @tsv" direction.json typhoon1005.json

結論

今天真正見識了 jq -s 拿來應用的好處:同時處理多個 json ,整併為一個陣列,使用索引取得元素內容,並儲存於變數,後面的運用就如同我們先前學到的各種方法。今天的修改可以參考 程式碼

💡想一想,如果風速的分級也能另存為一個 json,這樣又可以再讀入分級的資訊,將颱風的最大風速對應成"幾級風"來顯示,聽起來很不錯! 可以是明天的練習 😁

感謝自己今天也認真的練習。感謝大家互相幫忙,整理收拾山陀兒颱風留下的一地樹枝和各種砸落的看板 ❤️


上一篇
Day20: jq 的變數
下一篇
Day22: jq 字串轉數字
系列文
使用 jq 處理資料30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言