如何将 ps(1) 的输出转换为 JSON?

nwk*_*nwk 4 ps conversion json

我想将命令的输出转换ps为 JSON,以便将其作为结构化数据进行处理(在这种特殊情况下使用 jq)。我怎么做?

输出如下所示:

  PID TTY          TIME CMD
20162 pts/2    00:00:00 ps
28280 pts/2    00:00:02 zsh
Run Code Online (Sandbox Code Playgroud)

标题行始终存在。

nwk*_*nwk 12

有两种明显的方式来表示 JSON 中的柱状数据输出:作为数组的数组和作为对象的数组。在前一种情况下,您将输入的每一行都转换为数组;在后者中,到一个对象。

下面列出的命令至少适用于 Linux 上 procps-ng 的命令psps -l.

选项#1:数组数组

使用 Perl

您可以使用 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"]]
Run Code Online (Sandbox Code Playgroud)

使用 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"
  ]
]
Run Code Online (Sandbox Code Playgroud)

选项#2:对象数组

您可以通过从标题行中获取键名,将输入转换为具有有意义命名键的 JSON 对象数组。

这需要更多的努力,尤其是在 jq 中稍微有点棘手。然而,结果可以说是更具人类可读性。

使用 Perl

# 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"}]
Run Code Online (Sandbox Code Playgroud)

请注意,每个条目的键按任意顺序排列。这是 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"
  }
]
Run Code Online (Sandbox Code Playgroud)