我想从任意 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):
(根据您的操作系统安装 docker)
docker pull colisanr/morbig:latest
定义一个 shell 函数以方便使用:
morbig () { D=$(cd "$(dirname "$1")"; pwd) B=$(basename "$1") docker run \ -v "$D":/mnt \ colisanr/morbig:latest --as simple /mnt/"$B" }
确保包含 shell 脚本的目录可由 UID 1000 写入(docker 容器在容器内以用户“opam”运行,其 UID 1000)。
morbig your-shell-script-here.sh
生成的
your-shell-script-here.sh.sjson
JSON 将与 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()
。