从 morbig 生成的 JSON 文件中提取 CmdName_Word - Word

从 morbig 生成的 JSON 文件中提取 CmdName_Word - Word

我想从任意 shell 脚本中提取命令。我用过莫尔比格(向迈克尔·霍默获取建议!)从 shell 脚本生成 JSON 文件。

举个例子,这个 shell 脚本:

#!/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

但这感觉是错误的做法。我想jq告诉我“CmdName_Word”后面的“Word”后面的单词,但我不知道该怎么做。


如果您想在本地重现这些步骤(摘自https://github.com/colis-anr/morbig):

  1. (根据您的操作系统安装 docker)

  2. docker pull colisanr/morbig:latest

  3. 定义一个 shell 函数以方便使用:

     morbig () {
       D=$(cd "$(dirname "$1")"; pwd)
       B=$(basename "$1")
       docker run \
         -v "$D":/mnt \
         colisanr/morbig:latest --as simple /mnt/"$B"
     }
    
  4. 确保包含 shell 脚本的目录可由 UID 1000 写入(docker 容器在容器内以用户“opam”运行,其 UID 1000)。

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

  6. 生成的your-shell-script-here.sh.sjsonJSON 将与 shell 脚本位于同一目录中。

答案1

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

这里使用的表达式jq对文档中的每个实体进行递归,并测试每个实体的类型以查看它是否是数组。对于每个找到的也有第一个元素(即 string )的数组CmdName_Word,它继续提取第二个元素的第二个元素,即所查找的命令名称。

该表达式可以缩短为

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

...如果可用,则.[0]在 中使用,如果当前实体是数组,则它将是。select()我也直接.[1][1]用过select()

相关内容