オプション#1:配列の配列

オプション#1:配列の配列

ps構造化データで処理できるように、コマンドの出力をJSONに変換したい(次を使用)。ジャックこの特別な場合)。どうすればいいですか?

出力は次のとおりです。

  PID TTY          TIME CMD
20162 pts/2    00:00:00 ps
28280 pts/2    00:00:02 zsh

ヘッダー行は常に存在します。

ベストアンサー1

JSONには、列形式のデータ出力を表す2つの明確な方法があります。配列を配列に、配列をオブジェクトとして表現するものです。前者の場合、入力の各行をオブジェクトの配列に変換します。

ps以下のコマンドは、少なくともLinux上のprocps-ngコマンドの出力に適用されますps -l

オプション#1:配列の配列

パールを使う

PerlとCPANモジュールを使用して出力を変換できます。JSON::XS

# ps | perl -MJSON -lane 'my @a = @F; push @data, \@a; END { print encode_json \@data }'
[["PID","TTY","TIME","CMD"],["12921","pts/2","00:00:00","ps"],["12922","pts/2","00:00:00","perl"],["28280","pts/2","00:00:01","zsh"]]

JQの使用

あるいは、jq自体を使用して変換を実行できます。

# ps | jq -sR '[sub("\n$";"") | splits("\n") | sub("^ +";"") | [splits(" +")]]' 
[
  [
    "PID",
    "TTY",
    "TIME",
    "CMD"
  ],
  [
    "16694",
    "pts/2",
    "00:00:00",
    "ps"
  ],
  [
    "16695",
    "pts/2",
    "00:00:00",
    "jq"
  ],
  [
    "28280",
    "pts/2",
    "00:00:02",
    "zsh"
  ]
]

オプション#2:オブジェクトの配列

ヘッダー行からキー名を取得し、意味のある名前のキーを持つJSONオブジェクトの配列に入力を変換できます。

これにはより多くの努力が必要で、jqでは少し難しいです。しかし、結果は間違いなく人が読みやすくなります。

パールを使う

# ps | perl -MJSON -lane 'if (!@keys) { @keys = @F } else { my %h = map {($keys[$_], $F[$_])} 0..$#keys; push @data, \%h } END { print encode_json \@data }'
[{"TTY":"pts/2","CMD":"ps","TIME":"00:00:00","PID":"11030"},{"CMD":"perl","TIME":"00:00:00","PID":"11031","TTY":"pts/2"},{"TTY":"pts/2","CMD":"zsh","TIME":"00:00:01","PID":"28280"}]

各項目のキー順序は任意です。これはPerlハッシュの仕組みの産物です。

JQの使用

# ps | jq -sR '[sub("\n$";"") | splits("\n") | sub("^ +";"") | [splits(" +")]] | .[0] as $header | .[1:] | [.[] | [. as $x | range($header | length) | {"key": $header[.], "value": $x[.]}] | from_entries]'
[
  {
    "PID": "19978",
    "TTY": "pts/2",
    "TIME": "00:00:00",
    "CMD": "ps"
  },
  {
    "PID": "19979",
    "TTY": "pts/2",
    "TIME": "00:00:00",
    "CMD": "jq"
  },
  {
    "PID": "28280",
    "TTY": "pts/2",
    "TIME": "00:00:02",
    "CMD": "zsh"
  }
]

おすすめ記事