Ⅰ. 插件描述
A shell parser, formatter, and interpreter (sh/bash/mksh) - including shfmtⅡ. 基本信息
|
Ⅲ. 安装方法
使用Vundle管理器安装
在你的.vimrc下添加:Plugin 'mvdan/sh'
… 然后在Vim中运行以下命令:
:source %
:PluginInstall
对于Vundle版本 < 0.10.2,请用上面的Bundle替换Plugin。
使用NeoBundle管理器安装
在你的.vimrc下添加:NeoBundle 'mvdan/sh'
… 然后在Vim中运行以下命令:
:source %
:NeoBundleInstall
使用VimPlug管理器安装
在你的.vimrc下添加:Plug 'mvdan/sh'
… 然后在Vim中运行以下命令:
:source %
:PlugInstall
使用Pathogen管理器安装
在终端中运行以下命令:cd ~/.vim/bundle
git clone https://github.com/mvdan/sh
Ⅳ. 文档说明
# sh
A shell parser, formatter, and interpreter. Supports [POSIX Shell], [Bash], and
[mksh]. Requires Go 1.12 or later.
Quick start
To parse shell scripts, inspect them, and print them out, see the [syntax
examples](https://godoc.org/mvdan.cc/sh/syntax#pkg-examples).
For high-level operations like performing shell expansions on strings, see the
shell examples.
shfmt
GO111MODULE=on go get mvdan.cc/sh/v3/cmd/shfmt
shfmt formats shell programs. It can use tabs or any number of spaces to
- See canonical.sh for a quick look at its default
style.
You can feed it standard input, any number of files or any number of directories
to recurse into. When recursing, it will operate on .sh and .bash files and
ignore files starting with a period. It will also operate on files with no
extension and a shell shebang.
shfmt -l -w script.sh
Typically, CI builds should use the command below, to error if any shell scripts
in a project don't adhere to the format:
shfmt -d .
Use -i N to indent with a number of spaces instead of tabs. There are other
formatting options - see shfmt -h. For example, to get the formatting
appropriate for Google's Style guide, use shfmt -i 2 -ci.
If any [EditorConfig] files are found, they will be used to apply formatting
- If any parser or printer flags are given to the tool, no EditorConfig
- will be used. A default like
-i=0can be used for this purpose.
An example of the options available:
[*.sh]
# like -i=4
indent_style = space
indent_size = 4
shell_variant = posix # like -ln=posix
binary_next_line = true # like -bn
switch_case_indent = true # like -ci
space_redirects = true # like -sr
keep_padding = true # like -kp
# Ignore the entire "third_party" directory.
[third_party/**]
ignore = truePackages are available on [Alpine], [Arch], [Docker], [FreeBSD], [Homebrew],
[MacPorts], [NixOS], [Scoop], [Snapcraft], and [Void].
Replacing bash -n
bash -n can be useful to check for syntax errors in shell scripts. However,shfmt >/dev/null can do a better job as it checks for invalid UTF-8 and does
all parsing statically, including checking POSIX Shell validity:
$ echo '${foo:1 2}' | bash -n
$ echo '${foo:1 2}' | shfmt
1:9: not a valid arithmetic operator: 2
$ echo 'foo=(1 2)' | bash --posix -n
$ echo 'foo=(1 2)' | shfmt -p
1:5: arrays are a bash featuregosh
GO111MODULE=on go get mvdan.cc/sh/v3/cmd/gosh
Proof of concept shell that uses interp. Note that it's not meant to replace a
POSIX shell at the moment, and its options are intentionally minimalistic.
Fuzzing
This project makes use of [go-fuzz] to find crashes and hangs in both the parser
and the printer. To get started, run:
git checkout fuzz
./fuzz
Caveats
- When indexing Bash associative arrays, always use quotes. The static parser
will otherwise have to assume that the index is an arithmetic expression.
$ echo '${array[spaced string]}' | shfmt
1:16: not a valid arithmetic operator: string
$ echo '${array[dash-string]}' | shfmt
${array[dash - string]}$((and((ambiguity is not supported. Backtracking would complicate the
parser and make streaming support viaio.Readerimpossible. The POSIX spec
recommends to space the operands if $( ( is meant.
$ echo '$((foo); (bar))' | shfmt
1:1: reached ) without matching $(( with ))- Some builtins like
exportandletare parsed as keywords. This is to allow
statically parsing them and building their syntax tree, as opposed to just
keeping the arguments as a slice of arguments.
JavaScript
A subset of the Go packages are available as an npm package called [mvdan-sh].
See the _js directory for more information.
Docker
To build a Docker image, checkout a specific version of the repository and run:
docker build -t my:tag -f cmd/shfmt/Dockerfile .
This creates an image that only includes shfmt. Alternatively, if you want an
image that includes alpine, add --target alpine.
To use the Docker image, run:
docker run --rm -v $PWD:/mnt -w /mnt my:tag <shfmt arguments>
Related projects
- Alternative docker images - by jamesmstone, PeterDaveHello
- [format-shell] - Atom plugin for
shfmt - [micro] - Editor with a built-in plugin for
shfmt - [modd] - A developer tool that responds to filesystem changes, using
sh - [shell-format] - VS Code plugin for
shfmt - [Sublime-Pretty-Shell] - Sublime Text 3 plugin for
shfmt - [vim-shfmt] - Vim plugin for
shfmt