如何在Vim中的替换命令中重复替换搜索词在一行中出现的次数?
我想在不使用标签的代码中使用标签。到目前为止,我所做的实现选项卡的工作相当精巧:如何在Vim中的替换命令中重复替换搜索词在一行中出现的次数?,vim,replace,Vim,Replace,我想在不使用标签的代码中使用标签。到目前为止,我所做的实现选项卡的工作相当精巧: :%s/^ /\t/g :%s/^\t /\t\t/g . . . 问题:有没有办法用tab(\t)替换两个空格()在行首找到的次数?如果您特别想在行首将空格转换为制表符(反之亦然),有一个有用的:retab命令可以解决这个问题。例如: :重新开始!2将以两个为一组的空格转换为制表符 :设置expandtab,然后:重新设置!2将制表位(宽度为2)转换回空格 有关详细信息,请参见:h:retab(和:h'
:%s/^ /\t/g
:%s/^\t /\t\t/g
. . .
问题:有没有办法用tab(
\t
)替换两个空格(
)在行首找到的次数?如果您特别想在行首将空格转换为制表符(反之亦然),有一个有用的:retab
命令可以解决这个问题。例如:
将以两个为一组的空格转换为制表符:重新开始!2
,然后:设置expandtab
将制表位(宽度为2)转换回空格:重新设置!2
:h:retab
(和:h'ts'
)
这不是原始问题的通用解决方案,但我认为它涵盖了最常见的用例。使用:s regex没有通用的方法。您不能使
/g
修饰符向后看,否则它将不可用,并且如果不向后看,您无法可靠地检查您是否位于行的开头
通常唯一的方法是循环,如下所示:
:for i in range(100)
: %s/^\t*\zs /\t/e
:endfor
这是丑陋的,缓慢的和高度不受赞扬的。使用:retab
有(至少)三种替代技术与此案例相关
1。第一个利用前面的原子匹配
自然定义缩进步骤的语法。根据
问题语句,缩进步骤是一对相邻的空格
开头只有空格的字符
当然可以。根据这个定义,可以构造实际的
替换模式,从右到左:
:%s/\%(^ *\)\@<= /\t/g
3.第三个想法是通过Vim处理前导空间
脚本语言。一种方便的方法是使用
替换为:substitute
命令的表达式功能
(请参见:帮助子替换-\=
)。当以\=
开头时,替换项
命令字符串允许替换模式的匹配项
对于\=
之后指定的表达式的求值结果:
:%s#^ \+#\=repeat("\t",len(submatch(0))/2)
这不管用吗<代码>:%s/\t/g?您还可以使用
:retab
命令。说:设置ts=2 noet
,然后:重新开始代码>。然后将tabstop重置为您想要使用的值,例如::set ts=4
@glts:我会输入此注释作为获取rep的答案(因为这正是OP想要的)@埃克斯:是和否;)我想知道它是如何工作的,并将其用于其他目的。@gits:正如我的问题的注释中所述:这将把所有选项卡都改为空格。那不是我想要的,你说得对。我现在明白你的问题了。现在我也很想看到一个有效的解决方案…@glts:看看我的中列出的命令。谢谢,但正如前面所说的,retab不是一个好的选项,因为它会影响文件中的所有选项卡。如果retab不是您想要的,请使用我提供的for循环替换。正如我所解释的,这确实是只替换行开头的字符的唯一方法。一些解释?谢谢想了更多关于\%
,\@这真是太好了。我不明白为什么\@@Tom:这是因为在\@中使用了启发式,如Vim文档中所述(请参见:help/\@
:%s#^ \+#\=repeat("\t",len(submatch(0))/2)