同じ標準入力を2回処理し、出力を追加します。

同じ標準入力を2回処理し、出力を追加します。

次の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//行の先頭に1つがあると、有効な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

しかし、問題があります!

これは1つのコマンドで行う必要があります。これは、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処理し、処理されたテキストを出力します。

だから私が理解したところによると、stdinを2回読む必要があります(一度grep -v '^[ ]*//' | jq 'sort_by(.key)'、もう一度grep '^[ ]*//')。両方のコマンドの出力をstdoutに追加します。

この問題をどのように解決できますか?

アップデート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と同じ出力を提供するようです(コメントなしの行の前にコメントされた行)。

ベストアンサー1

コメント行とコメント以外の行を混合して挿入する方法はありません。これを別々のブロックとして処理し、別々に処理する必要があります。

コメント行を最初に出力しても問題ない場合は、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

今あなたの "1つのコマンドでこれを行う必要があります。自分自身のコマンド(プログラム、スクリプト)を生成するのを妨げるものは何もないことを覚えておいてください$PATH$HOME/binexport PATH="$PATH:$HOME/bin"~/.bash_profile~/.profile

おすすめ記事