jq 的開發狀況

Hacker News 上看到「Jaq – A jq clone focused on correctness, speed, and simplicity (github.com/01mf02)」這篇的時候,倒不是 jaq 本身如何,而是在 id=38465712 裡面提到了 jq 的發展停滯了五年左右,但最近又恢復了:

Well, taking into account that jq development has been halted for 5 years and only recently revived again, it's no wonder that bug reports have been sitting there for that time, both well known and new ones. I bet they'll get up to speed and slowly but surely clear the backlog that has built up all this time.

然後下面有提到 https://github.com/jqlang/jq/issues/2305#issuecomment-1572634869 這個,今年六月的時候開始重整團隊改善 bus factor,加入更多新的 maintainer 進來。

算是個好消息,朝向 community 的方式來發展...

與 jq 互相配合的 jc

Simon Willison 的 blog 上看到的工具:「jc」,專案的網站:「JSON CLI output utility」。

可以把許多種輸出結果轉成 JSON 格式:

CLI tool and python library that converts the output of popular command-line tools and file-types to JSON or Dictionaries. This allows piping of output to tools like jq and simplifying automation scripts.

所以就可以這樣用:

dig example.com | jc --dig

然後再丟給 jq

dig example.com | jc --dig | jq -r '.[].answer[].data'

支援的格式不少,在「Parsers」這段可以看到。

Ubuntu 22.04 後可以直接透過系統的 apt 安裝:「Ubuntu – Details of package jc in jammy」,在那之前也可以透過 pip 裝起來用...

等 Ubuntu 22.04 出了以後應該會變成標配安裝...

Amazon EBS 的 gp3 可以用在開機磁碟了

可以先參考「Amazon EBS 推出了 gp3」這篇,但剛出來的時候大家都有發現無論是透過 web console 還是透過 awscli,boot disk 都沒辦法改成 gp3,可是在官方的文件上又說可以用 gp3,所以就有人在 AWS 的 forum 上發問了:「EBS GP3 Boot Volume Issues」。

直到剛剛發現已經可以改成 gp3 了... 一個一個手動改當然也是 OK,但對於有一卡車 EBS 要換的人來說鐵定得弄指令來換,這邊搭配了 jq 一起改:

aws ec2 describe-volumes | jq '.Volumes[] | select(.VolumeType == "gp2") | .VolumeId' | xargs -n1 -P4 env aws ec2 modify-volume --volume-type gp3 --volume-id

這邊是把 gp2 都改成 gp3,沒有考慮到空間大小的問題 (因為超過 1TB 時 gp2 給的 IOPS 會比較多),另外 -P4 是平行四個 process 跑,改起來會快一些...

gron:把 JSON 結構轉成條列式的資料,方便後續的文字處理...

在「gron makes JSON more greppable」這邊看到 gron 這個工具,可以將 JSON 轉成條列式的資料 (或是反過來,將條列式的資料轉回 JSON)。

像是網站上給的範例之一:

▶ gron testdata/two.json 
json = {};
json.contact = {};
json.contact.email = "mail@tomnomnom.com";
json.contact.twitter = "@TomNomNom";
json.github = "https://github.com/tomnomnom/";
json.likes = [];
json.likes[0] = "code";
json.likes[1] = "cheese";
json.likes[2] = "meat";
json.name = "Tom";

這讓 grep 或是 sed 之類的工具會更好操作,不然得用 jq 盧半天...

在 CLI 下開關以及查詢 EC2 的狀態...

有時候需要開 Ubuntu 測試東西,會在 AWS 上開 EC2 起來測試,但開 console 太麻煩了,寫幾個 function 丟進 shell script 裡面比較乾脆。其中查詢 Ubuntu AMI 的程式出自「How do I know what Ubuntu AMI to launch on EC2?」這邊。

ec2.ls() 裡,我的 jq 版本比較舊,不過不影響我的 copy & paste,所以就沒有 hack 他了。新版的應該可以多加上 | @tsv 變成 tab 隔開 (沒測過,查資料時查到而已)。

ec2.run() 裡,我這邊是先到 console 上查出 security group 與 subnet 的 id,然後這邊 hard code 進去。我的預設是開 t2.medium,臨時要指定的話就 ec2.run t2.nano 就可以改開 t2.nano 了,不過要注意的是,這邊程式在查詢時的條件是 hvm:ebs,換的時候要注意 image 相容性...

# AWS-related
function ec2.ls() {
    aws ec2 describe-instances | \
        jq -c -M '.Reservations[] | .Instances[] | [.InstanceId, .InstanceType, .PublicIpAddress]'
}

function ec2.rm() {
    local INSTANCE_ID=${1:i-xxxxxxxxxxxxxxxxx}
    aws ec2 terminate-instances --instance-id ${INSTANCE_ID}
}

function ec2.run() {
    local INSTANCE_TYPE=${1:-t2.medium}
    aws ec2 run-instances --image-id $(ec2.ubuntu_ami()) --key-name gslin --security-group-ids sg-xxxxxxxx --instance-type ${INSTANCE_TYPE} --subnet-id subnet-xxxxxxxx
}

function ec2.ubuntu_ami() {
    curl -s "https://cloud-images.ubuntu.com/locator/ec2/releasesTable" | \
    sed '$x;$G;/\(.*\),/!H;//!{$!d};$!x;$s//\1/;s/^\n//' | \
    jq -c '.aaData[] | select(contains(["16.04", "us-east-1", "hvm:ebs"]))' | \
    grep -o 'ami-[a-z0-9]\+' | \
    head -1
}

這種工具自己用的順手比較重要,要什麼功能自己改自己加...

話說 Ubuntu 網站上的 JSON 居然吐出 malformed data (trailing comma),這是自己 printf() 之類硬幹出來的嗎... XD

用 jq 操作 JSON 文件

jq 用一陣子了 (因為配合著 AWS 官方的 AWS Command Line Interface 一起用),剛好看到有人介紹:「jq is sed for JSON」。

現在 Ubuntu 的 package repository 內都有 jq 了 (Ubuntu – Package Search Results -- jq),雖然版本舊了一點,不過基本功能都穩定了,除非有特別的需求,不然應該夠用。

照原文章的範例,假設 1.json 是這樣:

[
  {
    "type": "message",
    "user": "U024HFHU5",
    "text": "hey there",
    "ts": "1385407681.000003"
  },
  {
    "type": "message",
    "user": "U024HGJ4E",
    "text": "right back at you",
    "ts": "1385407706.000006"
  }
]

而你下這樣的 command 就可以抽出來:

$ jq "[.[] | { the_user: .user, the_text: .text }]" 1.json
[
  {
    "the_user": "U024HFHU5",
    "the_text": "hey there"
  },
  {
    "the_user": "U024HGJ4E",
    "the_text": "right back at you"
  }
]

很好用的工具 :o