Ps

如何將 ps(1) 的輸出轉換為 JSON?

  • September 16, 2021

我想將命令的輸出轉換ps為 JSON,以便將其作為結構化數據處理( 在這種特殊情況下使用jq )。我怎麼做?

輸出如下所示:

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

標題行始終存在。

在 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"]]

使用 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 中稍微複雜一些。然而,結果可以說是更具人類可讀性。

使用 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"}]

請注意,每個條目的鍵是任意順序的。這是 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"
 }
]

引用自:https://unix.stackexchange.com/questions/243484