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

Perl 如何将源文件的格式从2个空格缩进改为3个空格缩进?,perl,vim,indentation,Perl,Vim,Indentation,这个问题几乎与相同,只是我必须使用三个空格(公司编码指南)而不是四个空格,并且接受的解决方案只会使匹配的模式加倍。这是我的第一次尝试: :%s/^\(\s\s\)\+/\1 /gc 但这不起作用,因为四个空格会被三个空格取代。所以我认为我需要的是某种方法来计算模式匹配“+”的次数,并使用该数字来创建替换的另一面,但我觉得这个功能在Vim的正则表达式中可能不可用(如果您认为可能的话,请告诉我) 我还尝试手动进行替换,首先替换最大的缩进,然后替换下一个较小的缩进,直到我将其全部转换,但这很难跟踪

这个问题几乎与相同,只是我必须使用三个空格(公司编码指南)而不是四个空格,并且接受的解决方案只会使匹配的模式加倍。这是我的第一次尝试:

:%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-pe'mx;打印$res'
我最后的办法是编写一个Perl脚本来进行转换,但我希望在Vim中有一个更通用的解决方案,这样我就可以在将来重用这个想法来解决其他问题。

让维姆替你做

:设置sw=3
gg=G
第一个命令设置
shiftwidth
选项,即缩进量。第二行是:转到文件的顶部(
gg
),然后重新删除(
=
),直到文件的结尾(
G

当然,这取决于vim为您使用的语言提供了一个好的格式化程序。如果不是这样,事情可能会搞砸

Regexp方式。。。更安全,但不易理解:

:%s#^\(\s\s\)\+\\=重复(“”,strlen(子匹配(0))*3/2)\g
(我不得不做一些实验。)

两点:

  • 如果替换以
    \=
    开头,则它将作为表达式进行计算
  • 您可以使用许多东西来代替
    /
    ,因此
    /
    可用于分割

您要求的perl版本

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

(原件已备份到“YOUR_FILE.bak”):

编辑_文件时从vim:

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

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

shiftwidth的东西确实把我的文件弄得乱七八糟,但是正则表达式工作得很好!谢谢我尝试在vim帮助中查找,以了解有关“\=”的更多信息,但我不确定在帮助中查找什么。您能给我指一下有关它的文档吗?
:help sub replace expression
谢谢Amadan,标记为正确答案。我想知道是否有人可以告诉我,如果通过Perl regex发送解决方案,它可能会是什么样子,因为我可能需要在脚本中执行它?相关:在Vim SE
bash$ perl -pi.bak -e 's{^((?:  )+)}{"   " x (length($1)/2)}e' YOUR_FILE
:%!perl -pe 's{^((?:  )+)}{"   " x (length($1)/2)}e'