支持 bash 的 shell 解析器、格式化程序和解释器,包括 shfmt

作者:Sec-Labs | 发布时间:

工具介绍

一个shell解析器、格式化器和解释器。支持POSIX Shell、Bash和mksh。需要Go 1.17更高版本

工具地址

https://github.com/mvdan/sh

快速开始

要解析shell脚本,检查它们,并把它们打印出来,请看语法例子

对于高层次的操作,如对字符串进行shell扩展,请看shell例子

shfmt

go install mvdan.cc/sh/v3/cmd/shfmt@latest

shfmt 用于格式化 shell 程序。请看canonical.sh来快速了解它的默认样式。比如说。

shfmt -l -w script.sh

更多信息请见其manpage,可以直接查看Markdown或用scdoc渲染。

在Alpine, Arch, Debian, Docker, Fedora, FreeBSD, Homebrew, MacPorts, NixOS, Scoop, Snapcraft, Void和webi上都有软件包。

gosh

go install mvdan.cc/sh/v3/cmd/gosh@latest

使用interp的概念证明shell。请注意,它目前并不打算取代POSIX shell,而且它的选项也是有意的最小化。

模糊处理

我们使用Go的本地模糊支持,这需要Go 1.18或更高版本。比如说。

cd syntax
go test -run=- -fuzz=ParsePrint

注意事项

当对Bash关联数组进行索引时,总是使用引号。否则,静态分析器将不得不认为该索引是一个算术表达式。

$ echo '${array[spaced string]}' | shfmt
1:16: not a valid arithmetic operator: string
$ echo '${array[dash-string]}' | shfmt
${array[dash - string]}

不支持$((((的歧义。回溯会使解析器复杂化,并使通过io.Reader的流支持成为不可能。POSIX规范建议,如果$( ( 是指操作数,那么就给操作数加空格。

$ echo '$((foo); (bar))' | shfmt
1:1: reached ) without matching $(( with ))

一些内建函数,如 exportlet,被解析为关键词。这允许静态地构建它们的语法树,而不是把参数作为一个词的片断来保存。它还需要支持 declare foo=(bar)。注意,这意味着不支持像 declare {a,b}=c 这样的扩展。

JavaScript

Go软件包的一个子集以npm软件包的形式提供,称为mvdan-sh。更多信息请参见_js目录。

Docker

所有的发布标签都通过Docker发布,如v3.5.1。目前最新的稳定版发布为v3,最新的开发版发布为最新。这些镜像只包括shfmt;-alpine变体存在于Alpine Linux上。

要建立一个Docker镜像,请运行。

docker build -t my:tag -f cmd/shfmt/Dockerfile .

要使用一个Docker镜像,请运行。

docker run --rm -u "$(id -u):$(id -g)" -v "$PWD:/mnt" -w /mnt my:tag <shfmt arguments>

 

标签:工具分享