如何将源文件从2空格缩进改为3空格缩进?

8
这个问题与这个问题几乎相同,只是我需要用三个空格(公司编码规范)而不是四个,并且被接受的解决方案只会将匹配模式加倍。以下是我的第一次尝试:
:%s/^\(\s\s\)\+/\1 /gc 

但是这种方法行不通,因为四个空格会被替换成三个。所以我认为我需要一种方法来获取匹配"+"的次数,并使用该数字创建替换的另一侧,但我感觉这种功能在Vim的正则表达式中可能不可用(如果您认为可能可能,请告诉我)。
我还尝试手动进行替换,先替换最大的缩进,然后替换下一个较小的缩进,直到将所有内容都转换完成,但这样很难跟踪空格的数量:
:%s/^              \(\S\)/                     \1/gc

我可以使用Perl发送它,因为似乎Perl可能具有使用其扩展模式的能力。但是我无法在我的Perl版本中使其正常工作。这是我尝试计算a的代码:

:%!perl -pe 'm<(?{ $cnt = 0 })(a(?{ local $cnt = $cnt + 1; }))*aaaa(?{ $res = $cnt })>x; print $res'

如果没有更好的方法,我会写一个Perl脚本来进行转换,但我希望在Vim中找到一种更通用的解决方案,以便将来可以重复使用这个想法来解决其他问题。


谢谢Amadan,已标记为正确答案。我想知道如果使用Perl正则表达式发送解决方案会是什么样子,因为我可能需要在脚本中执行此操作? - stephenmm
相关:重新缩进糟糕缩进的代码 在Vim SE。 - kenorb
2个回答

8
让vim为您做这件事吗?
:set sw=3<CR>
gg=G

第一条命令设置了shiftwidth选项,这是您缩进的量。第二行表示:转到文件顶部(gg),并重新缩进(=)直到文件结尾(G)。
当然,这取决于vim是否有适合您使用语言的良好格式化程序。如果没有,可能会出现问题。
正则表达式方式...更安全,但不太容易理解:
:%s#^\(\s\s\)\+#\=repeat(' ',strlen(submatch(0))*3/2)#g

(我必须做一些实验。)

两个要点:

  • 如果替换以 \= 开头,则被视为表达式。
  • 你可以使用许多东西来代替 /,因此 / 可用于除法。

缩进宽度的设置真的搞乱了我的文件,但正则表达式却完美地工作了!谢谢!我尝试在vim帮助中查找更多关于'='的信息,但我不确定在帮助中该查找什么。你能指导我查找相关文档吗? - stephenmm
2
:help sub-replace-expression - phant0m

1

您所要求的 Perl 版本是...

从命令行执行(原地编辑,无备份):

bash$ perl -pi -e 's{^((?:  )+)}{"   " x (length($1)/2)}e' YOUR_FILE

(原地修改,原始文件备份为“YOUR_FILE.bak”):

bash$ perl -pi.bak -e 's{^((?:  )+)}{"   " x (length($1)/2)}e' YOUR_FILE

在编辑 YOUR_FILE 时使用 vim:

:%!perl -pe 's{^((?:  )+)}{"   " x (length($1)/2)}e'

正则表达式匹配行的开头,然后是一个或多个“两个空格”组(被捕获的集合)。替换模式是Perl表达式(因此有“e”修饰符),它计算被捕获的“两个空格”组的数量并创建相同数量的“三个空格”组的字符串。如果原始字符串中存在“额外”的空格,则在替换后保留该空格。所以如果之前有三个空格,在替换后将会变成四个,之前有五个空格的话,在替换后会变成七个等等。

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