jqの使い方まとめ

公開:2020/10/07
更新:2020/10/07
4 min読了の目安(約4300字TECH技術記事

jqの使い方でハマったところや便利な使い方をまとめます。

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

, []などをあとから追加する方法

ちょっと前までは,がなかったらerrorが出てた気がするんですが(気のせいか?)、今では,がなくても以下のようなjsonでもerrorが出ないので、あとから追加する方法が使えます。[1]とかしたいので、[]も追加します。

  • jq -s ".|= .+[]"
{ 
 "user" : "syui",
 "id" : "1"
}
{ 
 "user" : "test",
 "id" : "2"
}
$ cat tmp.json|jq -s ".|= .+[]"
[
	{ 
	 "user" : "syui",
	 "id" : "1"
	},
	{ 
	 "user" : "test",
	 "id" : "2"
	}
]

U+0000のerrorが出る場合

jq-1.5から改行が含まれていると、以下のようなerrorが出る場合があって、これが本当に厄介です。

$ echo "{\"text\":\"$text\"}"|jq .
parse error: Invalid string: control characters from U+0000-through-U+001F must be escaped at line 3, column 23

主な回避策は以下。特殊文字などが含まれている場合も有効です。

  • jq -n --arg var "$var"

  • jq -R tmp.txt

$ jq -n --arg text "$text" "{\"text\":\$text}"

$ text=`echo $text | jq -R`
$ echo "{\"text\":$text}" | jq .

\$text$textの違いに注意してください。

改行を削除する場合

  • jq <<< $text
$ jq . <<< $text

ダブルクオーテーションを取り除く場合

これは-rのオプションですね。よく使いますが見落としがちかもしれません。

  • jq -r ".user"
$ cat tmp.json|jq -r ".[].user"
syui
test

keyを指定して値を取り出す場合

  • jq "select(.name == \"syui\")
$ cat tmp.json
[
	{ 
	 "user" : "syui",
	 "id" : "1"
	},
	{ 
	 "user" : "test",
	 "id" : "2"
	}
]

$ cat tmp.json|jq -r ".[]|select(.user == \"syui\")"
{
  "user": "syui",
  "id": "1"
}

keyがあればそのkeyの値を取り出す場合

nullじゃなければという条件で検索します。

  • jq "select(.user !=null)"
$ cat tmp.json
[
	{ 
	 "user" : "syui",
	 "id" : "1"
	},
	{ 
	 "user" : "test",
	 "id" : "2"
	}
]

$ cat tmp.json|jq -r ".[]|select(.user !=null)|.user"
syui
test

配列の数を調べる場合

  • jq length
$ cat tmp.json
[
	{ 
	 "user" : "syui",
	 "id" : "1",
	 "link" : "syui.cf"
	},
	{ 
	 "user" : "test",
	 "id" : "2",
	 "link" : "example.com"
	}
]

$ cat tmp.json|jq length
2

$ cat tmp.json|jq ".[]|length"
3
3

$ cat tmp.json|jq ".[]|select(.user == \"syui\")|length"
3

keyがあるか調べる場合

  • jq "has(\"user\")"
$ cat tmp.json|jq ".[]|has(\"user\")"
true
true

2つのファイルをマージする場合

  • jq -s add tmp.json tmp2.json

以下の2つのファイルがあったとします。

[
	{ 
	 "user" : "syui",
	 "id" : "1",
	 "link" : "syui.cf"
	},
	{ 
	 "user" : "test",
	 "id" : "2",
	 "link" : "example.com"
	},
	{ 
	 "user" : "github",
	 "id" : "3",
	 "link" : "github.com"
	},
]
[
	{ 
	 "user" : "github",
	 "id" : "3",
	 "link" : "github.com"
	},
	{ 
	 "user" : "zenn",
	 "id" : "4",
	 "link" : "zenn.dev"
	}
]

これらをまとめるには単純にjq -s addします。

$ jq -s add tmp.json tmp2.json
[
  {
    "user": "syui",
    "id": "1",
    "link": "syui.cf"
  },
  {
    "user": "test",
    "id": "2",
    "link": "example.com"
  },
  {
    "user": "github",
    "id": "3",
    "link": "github.com"
  },
  {
    "user": "github",
    "id": "3",
    "link": "github.com"
  },
  {
    "user": "zenn",
    "id": "4",
    "link": "zenn.dev"
  }
]

重複するkeyがあるファイルをマージする場合

これは両者が同じkeyを有する場合のみ有効です。以下の2つのファイルではuser:syuiが重複しています。

したがって、単純にaddすると2つとも残ってしまいます。

これを1つに統合したいような場面を想定しています。

  • jq -s '.[0] * .[1]' tmp.json tmp2.json
{
  "var": {
    "aaa": {
      "user": "syui",
      "id": "1",
      "link": "syui.cf"
    },
    "bbb": {
      "user": "test",
      "id": "2",
      "link": "example.com"
    }
  }
}
{
  "var": {
    "aaa": {
      "user": "syui",
      "id": "1",
      "link": "syui.cf"
    },
    "ccc": {
      "user": "github",
      "id": "3",
      "link": "github.com"
    }
  }
}
$ jq -s '.[0] * .[1]' tmp.json tmp2.json
{
  "var": {
    "aaa": {
      "user": "syui",
      "id": "1",
      "link": "syui.cf"
    },
    "bbb": {
      "user": "test",
      "id": "2",
      "link": "example.com"
    },
    "ccc": {
      "user": "github",
      "id": "3",
      "link": "github.com"
    }
  }
}

keyの複数検索をする場合

  • jq ".[]|.user,.id"
$ cat tmp.json|jq ".[]|.user,.id"
"syui"
"1"
"test"
"2"
"github"
"3"

配列番号で配列を取り出す場合

  • jq ".[1]"
$ cat tmp.json|jq "keys|.[]"
0
1
2

$ cat tmp.json|jq ".[1]"
{
  "user": "test",
  "id": "2",
  "link": "example.com"
}

なお、0から始まるので最初の配列を取り出したければ、.[0]とします。

keyだけ取り出す場合

  • jq ".[]|keys"
$ cat tmp.json|jq ".[]|keys|.[]"
"id"
"link"
"user"
"id"
"link"
"user"
"id"
"link"
"user"