Bash

兩次處理相同的標準輸入並附加輸出

  • June 25, 2022

我有一個 json 文件,看起來像:

[
   {
       "key": "alt+down",
       "command": "-editor.action.moveLinesDownAction",
       "when": "editorTextFocus && !editorReadonly"
   },
   {
       "key": "alt+f12",
       "command": "editor.action.peekDefinition",
       "when": "editorHasDefinitionProvider && editorTextFocus && !inReferenceSearchEditor && !isInEmbeddedEditor"
   }
]
//  {
//      "key": "ctrl+shift+d",
//      "command": "workbench.action.toggleMaximizedPanel"
//  },
//  {
//      "key": "ctrl+shift+d",
//      "command": "-workbench.view.debug",
//      "when": "viewContainer.workbench.view.debug.enabled"
//  }

我想對這個文件進行排序。

jq如果行首有錯誤,則給出錯誤//,因為這不是有效的 json。

所以要對這個文件進行排序,我想出的命令是:

grep -v '^[ ]*//' keybindings.json | jq 'sort_by(.key)'

但我不想丟棄註釋行。因此,要獲得註釋行,我想出的命令是:

grep '^[ ]*//' keybindings.json

現在要解決我的問題,我可以簡單地做的是:

#!/bin/bash

SORTED_JSON=$(grep -v '^[ ]*//' keybindings.json | jq 'sort_by(.key)')
COMMENTED_JSON=$(grep '^[ ]*//' keybindings.json)

echo "$SORTED_JSON" >keybindings.json
echo "$COMMENTED_JSON" >>keybindings.json

但是有一個問題!

我必須在一個命令中執行此操作。這是因為,我是通過 vscode 設置來做到這一點的。

"filterText.commandList": [
   {
       "name": "Sort VSCode Keybindings",
       "description": "Sorts keybindings.json by keys. Select everything except the comment in fist line. Then run this command",
       "command": "jq 'sort_by(.key)'"
   }
]

command選中的文本作為標準輸入,進行處理,然後輸出處理後的文本。

所以,據我所知,我必須兩次閱讀標準輸入(一次grep -v '^[ ]*//' | jq 'sort_by(.key)'和第二次grep '^[ ]*//')。並將兩個命令輸出附加到標準輸出中。

我怎麼解決這個問題?

更新1:

我都試過了

cat keybindings.json| {grep -v '^[ ]*//' | jq 'sort_by(.key)' ; grep '^[ ]*//'}

cat keybindings.json| (grep -v '^[ ]*//' | jq 'sort_by(.key)' ; grep '^[ ]*//')

這些不顯示註釋行。

更新 2:

以下似乎接近我的預期。但是這裡註釋的行位於未註釋的行之前。

$ cat keybindings.json| tee >(grep -v '^[ ]*//' | jq 'sort_by(.key)') >(grep '^[ ]*//') > /dev/null 2>&1
   //  {
   //      "key": "ctrl+shift+d",
   //      "command": "workbench.action.toggleMaximizedPanel"
   //  },
   //  {
   //      "key": "ctrl+shift+d",
   //      "command": "-workbench.view.debug",
   //      "when": "viewContainer.workbench.view.debug.enabled"
   //  }
[
 {
   "key": "alt+down",
   "command": "-editor.action.moveLinesDownAction",
   "when": "editorTextFocus && !editorReadonly"
 },
 {
   "key": "alt+f12",
   "command": "editor.action.peekDefinition",
   "when": "editorHasDefinitionProvider && editorTextFocus && !inReferenceSearchEditor && !isInEmbeddedEditor"
 }
]

更新 3:

cat keybindings.json| (tee >(grep '^[ ]*//'); tee >(grep -v '^[ ]*//' | jq 'sort_by(.key)'))

或者,

cat keybindings.json| {tee >(grep '^[ ]*//'); tee >(grep -v '^[ ]*//' | jq 'sort_by(.key)')} 

似乎也提供與更新 3 相同的輸出(註釋行位於未註釋行之前)。

我知道沒有辦法插入混合註釋行和非註釋行;您必須將它們視為單獨的塊並單獨處理它們。

如果您不介意首先輸出註釋行,則可以這樣使用awk

awk '{ if ($0 ~ /^ *\/\//) { print } else { print | "jq \"sort_by(.key)\"" } }' keybindings.json

但是由於您希望註釋行出現在最後,您需要儲存註釋行並稍後輸出:

awk '
   # Define a convenience variable for the jq process
   BEGIN {
       jq = "jq \"sort_by(.key)\""
   }

   # Each line hits this. Either we save the comment or we feed it to jq
   {
       if ($0 ~ /^ *\/\//) { c[++i] = $0 }
       else { print | jq }
   }
   
   # Close the pipe to get its output and then print the saved comment lines
   END {
       close (jq);
       for (i in c) { print c[i] }
   }
' keybindings.json

現在,關於您的“我必須在一個命令中執行此操作”。請記住,沒有什麼能阻止您創建自己的命令(程序、腳本)。將必要的命令集放入文件中,使文件可執行,然後將其放入$PATH. 我一直使用and 我在我的and中$HOME/bin有等價物。export PATH="$PATH:$HOME/bin"``~/.bash_profile``~/.profile

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