Memo/JavaScript/jq

https://dexlab.net:443/pukiwiki/index.php?Memo/JavaScript/jq
 

jq: JSONのCLIパーサ

  • jq CLIツール
  • 整形
echo '{ "key1":"value1" }' | jq .
{
  "key1": "value1"
}
  • オプション
    • -r: ダブルクオーテーション等の引用符を出力しない
    • -c: コンパクト。1行に納める
  • 記事

sort, sort_by: ソート

  • sort: arrayをソート。逆順は「| reverse」を付ける
    echo '[4,3,2]' | jq 'sort'
    [
      2,
      3,
      4
    ]
  • sort_by: mapのarrayを「.id」でソート。逆順は「| reverse」を付ける
    echo '[{"id":4}, {"id":3}, {"id":2}]' | jq 'sort_by(.id)'
    [
      {
        "id": 2
      },
      {
        "id": 3
      },
      {
        "id": 4
      }
    ]

nullの扱い

  • .val != nullのデータだけ選択
    jq -n '{"key":"foo1", "val": 1},{"key":"foo2","val":null} | select(.val != null)'
    {
      "key": "foo1",
      "val": 1
    }
  • 配列から != nullの要素だけ選択
    jq -n '["a","b",null] | map(select(.!=null))'
    [
      "a",
      "b"
    ]

del(): 指定要素の削除

  • .valを削除
    jq -n '{"key":"foo1", "val": 1},{"key":"foo2","val":null} | del(.val)'
    {
      "key": "foo1"
    }
    {
      "key": "foo2"
    }

gojq: Go言語版jq


一部の配列を文字列へ変換したい。

  • 全体はtsvで出力。ResourceRecords[] は複数の値があるので、カンマ区切りに変換。AliasTargetの場合もある。
  • join()は配列しか受け取らないので、「[.ResourceRecords[].Value]」で配列に変換している。
    • 配列に変換しないと、「Cannot iterate over string」エラー。
    • nullが含まれていてもカンマが増える
  • 「| sort」でソートも出来るが、「,val1,val2」のように前にカンマが付く。
  • echo '
    {
        "ResourceRecordSets": [
            {
                "ResourceRecords": [
                    {
                        "Value": "ec2-xxx-xxx-xxx-001.ap-northeast-1.compute.amazonaws.com"
                    },
                    {
                        "Value": "ec2-xxx-xxx-xxx-002.ap-northeast-1.compute.amazonaws.com"
                    }
                ], 
                "Type": "CNAME", 
                "Name": "roundrobin.example.com.", 
                "TTL": 300
            }, 
            {
                "AliasTarget": {
                    "HostedZoneId": "XXXXXXXXXX", 
                    "EvaluateTargetHealth": false, 
                    "DNSName": "web-1234567890.ap-northeast-1.elb.amazonaws.com."
                }, 
                "Type": "A", 
                "Name": "www.example.com."
            }
       ]
    }
    ' | jq -r '.ResourceRecordSets[] | select(.Type | test("CNAME|AAAA|^A$")) | [.Name, .Type, ([.ResourceRecords[]?.Value, .AliasTarget?.DNSName] | join(","))] |@tsv'
    
    roundrobin.example.com.	CNAME	ec2-xxx-xxx-xxx-001.ap-northeast-1.compute.amazonaws.com,ec2-xxx-xxx-xxx-002.ap-northeast-1.compute.amazonaws.com,
    www.example.com.	A	web-1234567890.ap-northeast-1.elb.amazonaws.com.

検索: select()

  • td-agent(fluentd) で buffer_queue_length > 0 のものだけを選択
    curl -s localhost:24220/api/plugins.json | jq '.plugins[] | select(.buffer_queue_length > 0)'
  • 完全一致
    select(.Value == "example")
  • 正規表現を使って検索
    select(.Type | test("CNAME|AAAA|^A$"))
  • 「.DeleteOnTermination == false」ec2をterminateしても、自動削除されないEBSのvol-idを表示。手動で削除する必要あり。
    aws ec2 describe-instances --instance-ids i-xxxx --profile example > ec2.i-xxxx.json
    cat ec2.i-xxxx.json  | jq -r '.Reservations[].Instances[].BlockDeviceMappings[].Ebs | select(.DeleteOnTermination == false) | .VolumeId'

nullを無視して検索

select()する時にnullが混ざっていると「Cannot iterate over null (null)」が出る。

  • .[]?

    Like .[], but no errors will be output if . is not an array or object.

  • 例: Valueに"example2" を含むレコードを出力
    echo '{"ResourceRecordSets":[{"AliasTarget":{"HostedZoneId":"example","EvaluateTargetHealth":false,"DNSName":"example.ap-northeast-1.elb.amazonaws.com."},"Type":"A","Name":"example.com."},{"ResourceRecords":[{"Value":"example2.ap-northeast-1.elb.amazonaws.com."}],"Type":"CNAME","Name":"www.example.com.","TTL":300}]}' \
    | jq '.ResourceRecordSets[] | select(.ResourceRecords[]?.Value | test("example2"))'

出力形式指定: csv, tsv, etc

  • dict型をarray型へ変換後、@csv出力
    echo '[ { "name": "foo", "val": 10 }, { "name": "bar", "val": 20 }  ]' | jq -r '.[] | [.name, .val] | @csv'
    "foo",10
    "bar",20

件数、合計、平均、最大、最小

  • 件数: length
  • 合計: add
  • 平均: add/length
  • 最大: max
  • 最小: min
  • 例:valを元に計算
    echo '[ { "id": 1, "val": 10 }, { "id": 2, "val": 20 }  ]' | jq '[.[].val] | length, add, add/length, max, min'
    2  # length
    30 # add
    15 # add/length
    20 # max
    10 # min

インストール

  • CentOS 7: epelリポジトリにある
    sudo yum install jq --enablerepo=epel
  • Ubuntu 18.04 LTS:
    sudo apt install jq

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2019-10-11 (金) 13:06:44 (40d)