2020/01/15

jq

JSON 格式的應用現在已經隨處可見了,目前使用的程式語言都有相關支援的套件,如果要在 Linux 底下操作的話有一個非常好用的工具叫 jq,下面來展示應用範例

應用網址:https://jsonplaceholder.typicode.com/users

curl -s https://jsonplaceholder.typicode.com/users | jq .

我們會得到格式漂亮的結果

[
  {
    "id": 1,
    "name": "Leanne Graham",
    "username": "Bret",
    "email": "Sincere@april.biz",
    "address": {
      "street": "Kulas Light",
      "suite": "Apt. 556",
      "city": "Gwenborough",
      "zipcode": "92998-3874",
      "geo": {
        "lat": "-37.3159",
        "lng": "81.1496"
      }
    },
    "phone": "1-770-736-8031 x56442",
    "website": "hildegard.org",
    "company": {
      "name": "Romaguera-Crona",
      "catchPhrase": "Multi-layered client-server neural-net",
      "bs": "harness real-time e-markets"
    }
  }
]

而 jq 可以做 node 的搜寻,以上面那个例子

curl -s https://jsonplaceholder.typicode.com/users | jq .[0].name # "Leanne Graham"
curl -s https://jsonplaceholder.typicode.com/users | jq .[0].address.street # "Kulas Light"

使用 jq 的一些參數也可以達成 json encode 的功能:

test
#!/bin/bash

NAME=$1
AGE=$2

JSON_STRING=$(jq -n \
    --arg name "$NAME" \
    --arg age "$AGE" \
    '{name: $name, age: $age}')

echo $JSON_STRING
./test chan 40 # { "name": "chan", "age": "40" }

jq 没有驗證 json format 的功能,但我們可以利用一些 shell script 的特性辦到這件事

#!/bin/bash

function json_validator() {
    echo $1 | jq . &> /dev/null

    if [[ $? == 0 ]]; then
        echo "$1 is valid format"
    else
        echo "$1 is invalid format"
    fi
}

JSON='{"name": "chan"}'
json_validator "$JSON"
# {"name": "chan"} is valid format

JSON='{"name":}'
json_validator "$JSON"
# {"name":} is invalid format

jq 也可以使用自定義模組,在 ~/.jq 裡面可以將一些複雜但常用的內容先寫好

def blurry($f):
  ($f | ascii_upcase) as $ucf
  | to_entries[]
  | select((.key|ascii_upcase) | startswith($ucf))
  | .value;


def very_blurry($f):
  ($f | ascii_upcase) as $ucf
  | to_entries[]
  | select(.key | ascii_upcase | index($ucf))
  | .value;

這樣的話像搜尋 docker 的 config 的話就非常好用,像是 docker inspect test | jq '.. | blurry("config")?' | objects

搜尋語法
$ jq 'map(select(.id=="1234"))'
$ jq 'map(select(.id|index("1234")))'
$ jq 'map(select(.id|contains("1234")))'
$ jq 'map(select(.id|test("1234";"i")))'
$ jq 'map(select(.id|match("1234";"i")))'

沒有留言: