morbigで生成されたJSONファイルからCmdName_Wordを抽出する - Word

morbigで生成されたJSONファイルからCmdName_Wordを抽出する - Word

任意のシェルスクリプトからコマンドを抽出したいと思います。使ったモルビック(方へマイケル・ホーマーアドバイスを受けてください! )シェルスクリプトからJSONファイルを生成します。

たとえば、次のシェルスクリプトは次のようになります。

#!/bin/sh
echo hi
false || echo something
true && echo something

結果は次のJSONです。

[
  "Program_LineBreak_CompleteCommands_LineBreak",
  [ "LineBreak_Empty" ],
  [
    "CompleteCommands_CompleteCommands_NewlineList_CompleteCommand",
    [
      "CompleteCommands_CompleteCommands_NewlineList_CompleteCommand",
      [
        "CompleteCommands_CompleteCommand",
        [
          "CompleteCommand_CList",
          [
            "CList_AndOr",
            [
              "AndOr_Pipeline",
              [
                "Pipeline_PipeSequence",
                [
                  "PipeSequence_Command",
                  [
                    "Command_SimpleCommand",
                    [
                      "SimpleCommand_CmdName_CmdSuffix",
                      [
                        "CmdName_Word",
                        [ "Word", "echo", [ [ "WordName", "echo" ] ] ]
                      ],
                      [
                        "CmdSuffix_Word",
                        [ "Word", "hi", [ [ "WordName", "hi" ] ] ]
                      ]
                    ]
                  ]
                ]
              ]
            ]
          ]
        ]
      ],
      [ "NewLineList_NewLine" ],
      [
        "CompleteCommand_CList",
        [
          "CList_AndOr",
          [
            "AndOr_AndOr_OrIf_LineBreak_Pipeline",
            [
              "AndOr_Pipeline",
              [
                "Pipeline_PipeSequence",
                [
                  "PipeSequence_Command",
                  [
                    "Command_SimpleCommand",
                    [
                      "SimpleCommand_CmdName",
                      [
                        "CmdName_Word",
                        [ "Word", "false", [ [ "WordName", "false" ] ] ]
                      ]
                    ]
                  ]
                ]
              ]
            ],
            [ "LineBreak_Empty" ],
            [
              "Pipeline_PipeSequence",
              [
                "PipeSequence_Command",
                [
                  "Command_SimpleCommand",
                  [
                    "SimpleCommand_CmdName_CmdSuffix",
                    [
                      "CmdName_Word",
                      [ "Word", "echo", [ [ "WordName", "echo" ] ] ]
                    ],
                    [
                      "CmdSuffix_Word",
                      [
                        "Word",
                        "something",
                        [ [ "WordName", "something" ] ]
                      ]
                    ]
                  ]
                ]
              ]
            ]
          ]
        ]
      ]
    ],
    [ "NewLineList_NewLine" ],
    [
      "CompleteCommand_CList",
      [
        "CList_AndOr",
        [
          "AndOr_AndOr_AndIf_LineBreak_Pipeline",
          [
            "AndOr_Pipeline",
            [
              "Pipeline_PipeSequence",
              [
                "PipeSequence_Command",
                [
                  "Command_SimpleCommand",
                  [
                    "SimpleCommand_CmdName",
                    [
                      "CmdName_Word",
                      [ "Word", "true", [ [ "WordName", "true" ] ] ]
                    ]
                  ]
                ]
              ]
            ]
          ],
          [ "LineBreak_Empty" ],
          [
            "Pipeline_PipeSequence",
            [
              "PipeSequence_Command",
              [
                "Command_SimpleCommand",
                [
                  "SimpleCommand_CmdName_CmdSuffix",
                  [
                    "CmdName_Word",
                    [ "Word", "echo", [ [ "WordName", "echo" ] ] ]
                  ],
                  [
                    "CmdSuffix_Word",
                    [ "Word", "something", [ [ "WordName", "something" ] ] ]
                  ]
                ]
              ]
            ]
          ]
        ]
      ]
    ]
  ],
  [ "LineBreak_Empty" ]
]

次の出力を見たいです。

echo
false
echo
true
echo

...これで、基本コマンドのすべてのパラメーター、オプション、およびパラメーターを無視します。出力コマンドの順序は重要ではありません。エクスポートする前に(そして後で保存する前に)簡単にユニークにすることができるのは|sort -uボーナスポイントです。

私はこれをしました:

< simple.json jq flatten | grep -A2 CmdName_Word

しかし、これは間違ったアプローチのように感じます。 「CmdName_Word」の後に「Word」の後に続く単語を教えたいのですが、jqどうすればいいのかわかりません。


この手順をローカルで再現したい場合(から抜粋)https://github.com/colis-anr/morbig):

  1. (オペレーティングシステムに応じてdockerをインストールしてください)

  2. docker pull colisanr/morbig:latest

  3. 使いやすくするためにシェル関数を定義します。

     morbig () {
       D=$(cd "$(dirname "$1")"; pwd)
       B=$(basename "$1")
       docker run \
         -v "$D":/mnt \
         colisanr/morbig:latest --as simple /mnt/"$B"
     }
    
  4. シェルスクリプトを含むディレクトリにUID 1000として書き込むことができることを確認してください(Dockerコンテナは、UID 1000を持つコンテナ内でユーザー「opam」として実行されます)。

  5. morbig your-shell-script-here.sh

  6. 生成されたyour-shell-script-here.sh.sjsonJSONは、シェルスクリプトと同じディレクトリにあります。

答え1

$ jq -r '.. | select(type == "array" and .[0] == "CmdName_Word") | .[1][1]' file
echo
false
echo
true
echo

ここで使用される式はjqドキュメント内の各エンティティに対して繰り返され、各エンティティの種類をテストして配列であることを確認します。最初の要素である文字列を含む見つかった配列ごとに、2番目の要素のCmdName_Word2番目の要素(探しているコマンド名)を抽出します。

この表現は次のように短縮できます。

jq -r '.. | select(.[0]? == "CmdName_Word")[1][1]' file

...可能な場合.[0]に使用され、配列の場合は現在のエンティティになります。私もselect()自分で.[1][1]使ってみましたselect()

関連情報