nikkie-ftnextの日記

イベントレポートや読書メモを発信

jqを使ってテキストファイルをJSONに整形する

はじめに

大吉祥寺.pmありがとうございました!
Perl Mongerになった nikkieです。

jqについての学びのアウトプットです。

目次

JSONを作りたい

素材

emily.txt1

大和撫子に憧れる雅で可憐なイギリス人アイドル。
「・・・お、お喋りは大和撫子らしくありませんよね?」

作りたいJSON

{
  "name": "エミリースチュアート",
  "description": "大和撫子に憧れる雅で可憐なイギリス人アイドル。\n「・・・お、お喋りは大和撫子らしくありませんよね?」",
}

今回の実装方法

% jq --version
jq-1.6

テキストファイルを読み込んでひとつなぎのテキストを作る

-Rでテキストファイルを読み込みます2
各行が文字列のJSON Linesとして読み込みました。

% jq -R '.' emily.txt
"大和撫子に憧れる雅で可憐なイギリス人アイドル。"
"「・・・お、お喋りは大和撫子らしくありませんよね?」"

--slurp3を使って文字列からなる配列を得ます。
これはjoin関数で1つのテキストにまとめられます。

% jq -R '.' emily.txt | jq --slurp
[
  "大和撫子に憧れる雅で可憐なイギリス人アイドル。",
  "「・・・お、お喋りは大和撫子らしくありませんよね?」"
]
% jq -R '.' emily.txt | jq --slurp | jq 'join("\n")'
"大和撫子に憧れる雅で可憐なイギリス人アイドル。\n「・・・お、お喋りは大和撫子らしくありませんよね?」"

JSONを作るまでできます。

% jq -R '.' emily.txt | jq --slurp | jq 'join("\n") | {"description": .}'
{
  "description": "大和撫子に憧れる雅で可憐なイギリス人アイドル。\n「・・・お、お喋りは大和撫子らしくありませんよね?」"
}

複数のJSONをaddで足し合わせる

2つのJSONを足し合わせます。
1つは上で作ったdescriptionのJSON

nameのJSONは以下のようにして作ります。

% jq --null-input '{"name": "エミリースチュアート"}'
{
  "name": "エミリースチュアート"
}

オブジェクトどうしをaddで足せちゃうんですね〜(Pythonで言う辞書のマージ)。
ファイルに保存して足します。

% jq --slurp 'add' name.json description.json
{
  "name": "エミリースチュアート",
  "description": "大和撫子に憧れる雅で可憐なイギリス人アイドル。\n「・・・お、お喋りは大和撫子らしくありませんよね?」"
}

--slurp時点では配列に入ります。

% jq --slurp '.' name.json description.json
[
  {
    "name": "エミリースチュアート"
  },
  {
    "description": "大和撫子に憧れる雅で可憐なイギリス人アイドル。\n「・・・お、お喋りは大和撫子らしくありませんよね?」"
  }
]

ファイルを使わない書き方

% jq --slurp 'add' <(jq --null-input '{"name": "エミリースチュアート"}') <(jq -R '.' emily.txt | jq --slurp | jq 'join("\n") | {"description": .}')
{
  "name": "エミリースチュアート",
  "description": "大和撫子に憧れる雅で可憐なイギリス人アイドル。\n「・・・お、お喋りは大和撫子らしくありませんよね?」"
}

終わりに

jqを使ってテキストファイルをJSONに整形するのを通して学びがありました。
なお実際は、テキストファイルの代わりに別のjqコマンドが出力したテキストの処理でした。

  • -RJSONの文字列としてテキストファイルの各行を読み込める
    • --slurpで1つの配列に入れて処理できる
  • --null-input、固定値のJSONを作るときに使える
  • JSON--slurpで配列に入れてからadd。1つのJSONにまとめられた

jqを使ってjqが作れる(jqjq)を聞いたことがあったのですが、今回の経験はたしかにその可能性を感じさせるものでした!


  1. ソースはこちらです
  2. 前回の登場
  3. 前回の登場