jcを使ってUnixコマンド結果をJSON形式に変換する

2022.04.12

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Introduction

jcは、標準的なUnixコマンドの出力を受け取って
その出力をJSONにパースするという、python製ツールです。
(コマンドラインまたはpythonのモジュールとして使用可能)

例えば、Unixコマンド結果を少し加工したり一部の出力だけほしいときには
ちょっとしたスクリプトを書いたりします。
そんなとき、Unixコマンドの出力形式がJSON形式で扱えれば
スクリプトを書く手間が多少は省けます。

今回はUnixコマンド出力結果をJSON形式に変換するツールの
jcを紹介します。

Setup

インストールはMacならHomebrewで可能です。

% brew install jc

pipでも可能。

%pip3 install jc

その他、各種パッケージマネージャでインストールできるので、 こちらを参照してください。

Try jc

jcは標準入力からパイプを使って入力されたデータを受け取り、
直前のコマンドの出力をJSONで標準出力に出力します。
使い方は↓のようになります。

COMMAND | jc PARSER [OPTIONS]

ls結果をJSON形式に変換したい場合は下記のようにします。
lsコマンドの結果をパイプでうけとり、jcのlsパーサーを指定してJSON形式に変換しています。

% ls -la | jc --ls

[{"filename":".","flags":"drwxr-xr-x","links":4,"owner":"nakamura.shuta","group":"staff","size":128,"date":"Apr 8 15:19"},{"filename":"..","flags":"drwxr-xr-x","links":7,"owner":"nakamura.shuta","group":"staff","size":224,"date":"Apr 8 15:19"},{"filename":"app.js","flags":"-rw-r--r--@","links":1,"owner":"nakamura.shuta","group":"staff","size":3463,"date":"Apr 7 10:49"},{"filename":"foo.txt","flags":"-rw-r--r--","links":1,"owner":"nakamura.shuta","group":"staff","size":0,"date":"Apr 6 12:19"}]

変換するコマンドの前にjcを付与してもOKです。

jc [OPTIONS] COMMAND
% jc ls -la
・・・

pingのように、コマンド実行後に処理を開始して結果を
JSON linesで1行ずつうけとるコマンドもあります。 
こういったケースではStreaming Parserを指定します。
Streaming Parserを使うとコマンドのパースに必要なメモリを削減して、
高速なデータが可能になります。

% ping 127.0.0.1 | jc --ping-s
{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":0,"ttl":64,"time_ms":0.051}
{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":1,"ttl":64,"time_ms":0.174}
・・・

ls -lのStreaming Parser。

% ls -l | jc --ls-s
{"filename":"app.js","flags":"-rw-r--r--@","links":1,"owner":"nakamura.shuta","group":"staff","size":3463,"date":"Apr 7 10:49"}
{"filename":"foo.txt","flags":"-rw-r--r--","links":1,"owner":"nakamura.shuta","group":"staff","size":0,"date":"Apr 6 12:19"}

jc結果をjqとパイプでつないで、任意のフィールドだけ取得することもできます。
↓はls結果をjcでJSON化して、jqでパーミッション用のフィールドのみを抽出しています。

ls -la | jc --ls | jq ".[].flags"
"drwxr-xr-x"
"drwxr-xr-x"
"-rw-r--r--@"
"-rw-r--r--"

jcとjqを組み合わせることで、Unixコマンドと
JSONを操作するライブラリやツール間をブリッジしてくれます。
ちなみに、csv ・ yaml ・ /etc/hosts ・ iniなども
パーサーがあるので、jcでJSONへの変換が可能です。

参照:https://github.com/kellyjonbrazil/jc#examples

Custom Parsers

主要なコマンドについては
デフォルトでパーサーが用意されてますが、
対応していないコマンド(自作のシェルなども含む)もあります。

そういったケースでは、自分でパーサーを記述することができます。
※デフォルトのパーサーを上書きすることも可能

References