如何在vim中自动删除行末空格?

224

我在Git提交一些文件时遇到了“尾随空格”错误。

我想在保存Python文件之前自动删除这些尾随空格字符。

你能否配置Vim来实现这个功能?如果可以,怎么做?


3
不仅涉及Python。 - user3850
2
使用我的DeleteTrailingWhitespace插件。 - Ingo Karkat
14个回答

224

我在这里找到了答案。

将以下内容添加到我的 .vimrc 文件中就可以解决问题:

autocmd BufWritePre *.py :%s/\s\+$//e

结尾处的e标志表示如果搜索模式失败,该命令不会发出错误信息。请参见:h :s_flags 了解更多信息。


22
每次保存时光标位置都会改变。有没有可能避免这种情况发生? - stepancheg
6
既然这是该问题的事实答案,也许应该更新以保持光标位置。 - Edu Felipe
1
gi跳转到最后插入文本的位置(不一定是在:%s命令之前的光标位置),而:%!sed -r 's/\s+$//'则跳转到文件开头。我不明白keepjumps应该如何使用,:keepjumps :%s/\s+$//e似乎没有任何不同。我使用的是:%s/\s\+$//e|normal '',它似乎按照我的预期工作(回到使用:%s命令之前的光标位置)。 - humodz
3
这也将删除多行字符串尾部的空格,但这在某些情况下可能不是所期望的。但我想没有简单的方法可以避免这种情况? - luator
4
或许你可以明确指出,结尾的 e 表示如果没有找到匹配的模式,vi 不认为替换命令失败。 - LLenain
显示剩余7条评论

183

以上内容的编译以及保存光标位置:

function! <SID>StripTrailingWhitespaces()
  if !&binary && &filetype != 'diff'
    let l:save = winsaveview()
    keeppatterns %s/\s\+$//e
    call winrestview(l:save)
  endif
endfun

autocmd FileType c,cpp,java,php,ruby,python autocmd BufWritePre <buffer> :call <SID>StripTrailingWhitespaces()

如果你想将这个应用于保存任何文件,省略第二个 autocmd 并使用通配符 *

autocmd BufWritePre,FileWritePre,FileAppendPre,FilterWritePre *
  \ :call <SID>StripTrailingWhitespaces()

9
您可以通过保存最后一次搜索并在需要时还原它来改善功能。让_s=@/,@/=_s。 - xApple
4
我删除了“autocmd FileType c,cpp,java,php,ruby,python”这部分,让它适用于所有文件。 - swt83
10
在函数内部,保存和恢复上次的搜索并不必要——离开函数上下文会自动处理。 - Tobias
3
如果您希望它适用于所有文件,还需要将“<buffer>”替换为“*”。请注意不要改变原来的意思。 - cadlac
4
如果在替换命令前添加 keepp 前缀,则不会修改你的搜索历史记录,例如 keepp %s/\s\+$//e - jeberle
显示剩余7条评论

70

我通常也有一个:

match Todo /\s\+$/

为了让行末的空格显示出来,我在.vimrc文件中添加了以下配置:

highlight Todo ctermbg=yellow ctermfg=black guibg=yellow guifg=black
match Todo /s\+$/

其中,Todo是一个语法高亮的组名,它用于高亮关键字,如TODOFIXMEXXX。它默认有一个非常难看的黄色背景,我发现它最适合用来突出显示代码中不应该出现的内容 :-)


7
你可以设置列表并设置listchars+=trail:来显示结尾的空格。 - Oli
非常好 - 这是自动删除尾随空格(即使我可能没有意识到它,或者当我只是在同一个文件中工作时,它是别人的代码)和不做任何处理之间的完美折衷。谢谢。 - Daniel Hershcovich
2
不幸的是,我最喜欢的配色方案Zenburn没有高亮显示。 - Peter Long
@PeterLong,在railscasts主题中也不起作用。使用 :hi Todo 进行检查。所以我浏览了一下 :hi <Tab>:help hi。我考虑了 CursorError,但我想我会尝试 match VisualNOS /\s\+$/。我可能会将其与其他答案中的一些 autocmd 结合使用。 - Brady Trainor

56

我既强调现有的尾随空格,也清除尾随空格。

我将我的编辑器(vim)配置为显示末尾的空格,例如:

enter image description here

在我的.vimrc底部加上以下内容:

highlight ExtraWhitespace ctermbg=red guibg=red
match ExtraWhitespace /\s\+$/
autocmd BufWinEnter * match ExtraWhitespace /\s\+$/
autocmd InsertEnter * match ExtraWhitespace /\s\+\%#\@<!$/
autocmd InsertLeave * match ExtraWhitespace /\s\+$/
autocmd BufWinLeave * call clearmatches()

我会在保存文件时自动将其从文件中“剥离”,在我的情况下是针对 *.rb 的 ruby 文件,同样的操作也可以在我的 ~/.vimrc 中实现

function! TrimWhiteSpace()
    %s/\s\+$//e
endfunction
autocmd BufWritePre     *.rb :call TrimWhiteSpace()

太好了!谢谢!我特别喜欢这个函数。 - EHM

13

以下是一种可以按多个文件类型过滤的方法。

autocmd FileType c,cpp,python,ruby,java autocmd BufWritePre <buffer> :%s/\s\+$//e

每个文件:autocmd FileType * autocmd BufWritePre <buffer> :%s/\s+$//e - JREAM

10

我在VIM Wikia - 删除不需要的空格评论中发现了这个解决方案。

我真的很喜欢它。在不需要的空格上添加.

输入图像描述

把这段代码放到你的.vimrc文件中

" Removes trailing spaces
function TrimWhiteSpace()
  %s/\s*$//
  ''
endfunction

set list listchars=trail:.,extends:>
autocmd FileWritePre * call TrimWhiteSpace()
autocmd FileAppendPre * call TrimWhiteSpace()
autocmd FilterWritePre * call TrimWhiteSpace()
autocmd BufWritePre * call TrimWhiteSpace()

8
这是从http://blog.kamil.dworakowski.name/2009/09/unobtrusive-highlighting-of-trailing.html复制并粘贴的(该链接已失效,但下面是你需要的部分)。
“这样做的好处是不会突出显示你在行末输入的每个空格,只有当你打开文件或离开插入模式时才会突出显示。非常漂亮。”
highlight ExtraWhitespace ctermbg=red guibg=red
au ColorScheme * highlight ExtraWhitespace guibg=red
au BufEnter * match ExtraWhitespace /\s\+$/
au InsertEnter * match ExtraWhitespace /\s\+\%#\@<!$/
au InsertLeave * match ExtraWhiteSpace /\s\+$/

1
博客链接似乎已经失效了。 - Tobias
相同的解决方案可以在此链接中找到,在“使用match命令”下面。 - ryanjdillon

5
这是我做的方式。说实话,我不记得从哪里抄来的了。
autocmd BufWritePre * :call <SID>StripWhite()
fun! <SID>StripWhite()
    %s/[ \t]\+$//ge
    %s!^\( \+\)\t!\=StrRepeat("\t", 1 + strlen(submatch(1)) / 8)!ge
endfun

2
嗯,如果你最终打开二进制文件,那么在“*”上执行此操作是非常危险的,因为它们可能会变得非常糟糕。 - mat
是的,也许不是最聪明的选择,但我也不会用 vim 作为十六进制编辑器。除非你保存,否则它不会执行。 - gregf
我认为这比列出您可能使用的每种文件类型要好,不是吗?我使用rb、php、cs、html、sass、css、js、coffee、xml、xslt、pl等等。有没有一个折中的办法? - Derek Prior
4
除非你在vim中写入二进制文件,否则这可能永远不会成为问题。 - gregf
在第一个%s中,全局(g)标志似乎和行尾空格一样无用 :-) - Jens

3

简单地去除文件末尾的空格并不适用于所有情况。它可以在一开始就按照这个政策进行的项目中工作,因此没有你自己在即将提交的修改中添加的这种空格。

假设你只希望不添加新的末尾空格,而不影响你未编辑的行中现有的空格,以便让你的提交不受与你的工作无关的更改的影响。

在这种情况下,使用 git,你可以使用像这样的脚本:

#!/bin/sh

set -e # bail on errors

git stash save commit-cleanup
git stash show -p | sed '/^\+/s/ *$//' | git apply
git stash drop

也就是说,我们先将更改存储起来,然后在将更改应用到工作目录时,过滤掉差异中所有+行的尾随空格。如果此命令管道执行成功,我们就会丢弃存储。


2

对于想要针对特定文件类型运行它的人(文件类型并不总是可靠的):

autocmd BufWritePre *.c,*.cpp,*.cc,*.h,*.hpp,*.py,*.m,*.mm :%s/\s\+$//e

或者使用vim7:

autocmd BufWritePre *.{c,cpp,cc,h,hpp,py,m,mm} :%s/\s\+$//e

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接