Text-Processing

Nushell:將列表轉換為表格

  • May 4, 2022

有沒有一種慣用的方法可以將類似記錄的列表轉換為 Nushell 中的表?

我正在使用Stack Exchange API並獲取以下結果:

let questions = ('[
 {
   "tags":
   [
     "nushell"
   ],
   "title": "Nushell: Convert list to table"
 },
 {
   "tags":
   [
     "ssh",
     "tar"
   ],
   "title": "tar through ssh session",
   "closed_reason": "Duplicate"
 }
]' | from json)

請注意,closed_reason只有已關閉的問題才會返回,當然。這是有道理的——對於大多數問題,API 無需浪費頻寬返回空欄位。

但這樣一來,$questions就變成了list<any>Nushell中的一個。這意味著像這樣的操作:

> $questions | group-by closed_reason

…導致(邏輯上)cannot find column錯誤。

所有結果都需要具有相同的結構才能正常工作。例如,如果所有結果都有closed_reason’,像這樣:

let questions = ('[
 {
   "tags":
   [
     "nushell"
   ],
   "title": "Nushell: Convert list to table",
   "closed_reason": ""
 },
 {
   "tags":
   [
     "ssh",
     "tar"
   ],
   "title": "tar through ssh session",
   "closed_reason": "Duplicate"
 }
]' | from json)

然後$questions | describe變成:

table<tags: list<string>, title: string, closed_reason: string>

並且$questions | group-by closed_reason會工作。

有沒有辦法將列表轉換/“規範化”為表格?

我已經嘗試過(使用原始list<any>結果):

> $questions | table | group-by closed_reason
# obviously doesn't work, since the table command is just for rendering
# but worth a shot

> $questions | to csv | from csv | group-by closed_reason
# works, but loses the tag lists

> $questions | transpose | transpose | headers | reject column0 | to json
# Almost works, but still results in a list<any>
# since the first question's closed_reason becomes null
> $questions | transpose | transpose | headers | reject column0 | group-by closed_reason
# results in "can't convert nothing to string"

終於找到了答案。help --find def當我發現適當命名的(但未在 Nushell Book 中引用)命令時,我碰巧正在尋找與 完全不同的東西default,該命令本質上是 Nushell 內置的,用於執行@Kusalananda 推薦的相同操作jq

因此,問題中的範例可以通過以下方式修復:

> $questions | default "" closed_reason | group-by closed_reason
╭───────────┬───────────────╮
│           │ [table 1 row] │
│ Duplicate │ [table 1 row] │
╰───────────┴───────────────╯

結果是一個真正的 Nushell 表對象:

> $questions | default "" closed_reason | describe
table<tags: list<string>, title: string, closed_reason: string>

有了這些,我就可以開始對 Stack API 進行一些切片和切塊了:

> $questions |
     default "" closed_reason | 
     where closed_reason == "Duplicate" |
     update tags { $in.tags | str collect ','}
     
╭───┬─────────┬─────────────────────────┬───────────────╮
│ # │  tags   │          title          │ closed_reason │
├───┼─────────┼─────────────────────────┼───────────────┤
│ 0 │ ssh,tar │ tar through ssh session │ Duplicate     │
╰───┴─────────┴─────────────────────────┴───────────────╯

nu不幸的是,我對外殼不熟悉。不過,您絕對可以將數據作為 JSON 傳遞給jq,添加帶有空字元串值的缺失鍵,然後將其轉換回 shell 的內部表示。

在這裡,我正在更新questions變數,但您可以將jq命令標記到原始let命令上,而不是不必要地來迴轉換數據。

let questions = ($questions | to json | jq '.[].closed_reason += ""' | from json)

然後您可以按以下方式對其進行分組closed_reason

〉$questions | group-by closed_reason
╭───────────┬───────────────╮
│           │ [table 1 row] │
│ Duplicate │ [table 1 row] │
╰───────────┴───────────────╯

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