我想从任意 shell 脚本中提取命令。我使用morbig(向Michael Homer 的建议致敬!)从 shell 脚本生成 JSON 文件。
举个例子,这个 shell 脚本:
#!/bin/sh
echo hi
false || echo something
true && echo something
Run Code Online (Sandbox Code Playgroud)
结果如下 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" ]
]
Run Code Online (Sandbox Code Playgroud)
我希望看到以下内容的输出:
echo
false
echo
true
echo
Run Code Online (Sandbox Code Playgroud)
...现在忽略基本命令的任何参数、选项和参数。输出命令的顺序并不重要。如果在输出之前很容易使它们独一无二(|sort -u
之后保存),那就加分了。
我已经做到了:
echo
false
echo
true
echo
Run Code Online (Sandbox Code Playgroud)
但这感觉是错误的做法。我想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"
}
Run Code Online (Sandbox Code Playgroud)
确保包含 shell 脚本的目录可由 UID 1000 写入(docker 容器在容器内以用户“opam”运行,其 UID 1000)。
morbig your-shell-script-here.sh
生成的your-shell-script-here.sh.sjson
JSON 将与 shell 脚本位于同一目录中。
$ jq -r '.. | select(type == "array" and .[0] == "CmdName_Word") | .[1][1]' file
echo
false
echo
true
echo
Run Code Online (Sandbox Code Playgroud)
这里使用的表达式jq
对文档中的每个实体进行递归,并测试每个实体的类型以查看它是否是数组。对于每个找到的也有第一个元素(即 string )的数组CmdName_Word
,它继续提取第二个元素的第二个元素,即所查找的命令名称。
该表达式可以缩短为
jq -r '.. | select(.[0]? == "CmdName_Word")[1][1]' file
Run Code Online (Sandbox Code Playgroud)
...如果可用,则.[0]
在 中select()
使用,如果当前实体是数组,则它将是。我也.[1][1]
直接用过select()
。
归档时间: |
|
查看次数: |
250 次 |
最近记录: |