将单词替换为找到它的次数

时间:2012-03-26 10:00:42

标签: vim replace

我想在不使用它们的代码中使用制表符。到目前为止,我所做的实现制表符非常简单:

%s/^  /\t/g
%s/^\t  /\t\t/g
..

问题:有没有办法用标签()替换两个空格(\t)在一行开头找到它的次数?

3 个答案:

答案 0 :(得分:3)

如果您特别想要在行的开头将空格转换为制表符(或反之亦然),那么有用的:retab命令可以解决这个问题。例如:

  • :retab! 2会将两个一组的空格转换为标签
  • :set expandtab然后:retab! 2会将tabstops(宽度为2)转换回空格

有关详细信息,请参阅:h :retab(和:h 'ts')。

这不是原始问题的一般解决方案,但我认为它涵盖了最常见的用例。

答案 1 :(得分:3)

(至少)有三种与此案相关的替代技术。

第一个利用前面的原子匹配语法 自然地定义了一个缩进的步骤。根据问题陈述, 缩进步骤是一对相邻的空格字符,前面没有任何内容 但是从行首开始的空格。按照这个定义,可以 从右到左构建实际的替代模式。

:%s/\%(^ *\)\@<=  /\t/g

实际上,该模式指定出现两个文字空格字符 跟随前一个原子的零宽度\@<=匹配,即 模式^ *包含在分组括号\%( / \)中。这些非捕获 因为那里使用括号而不是通常捕获括号\( / \) 不需要进一步参考匹配的前导空格。由于g flag,上面的:substitute命令通过前导空格对 对,并用单个制表符替换它们。

第二种技术采用不同的方法。而不是分开匹配 缩进级别,可以打破以空格字符开头的每一行 分为两个:一个包含原始行的缩进空格, 另一个拿着剩下的。之后,可以直接更换 第一行上的所有空间对,并将这些行连接起来 在一起。

:g/^ /s/^ \+/&\r/|-s/  /\t/g|j!

第三个想法是通过Vim脚本处理前导空格 语言。一种方便的方法是使用替代品 :substitute命令的表达式功能(参见:help sub-replace-\=)。 使用\=查找命令的替换字符串,可以替换 模式的匹配与表达式的评估结果 在\=之后指定。

:%s#^ \+#\=repeat("\t",len(submatch(0))/2)

答案 2 :(得分:0)

没有一般的方法可以使用:s regex's。您无法使/g修饰符向后看,否则它将无法使用,并且您无法可靠地检查您是否在行的开头而不向后看。

这样做的唯一方法就是循环,如下所示:

:for i in range(100)
:   %s/^\t*\zs  /\t/e
:endfor

哪个丑陋,缓慢而且非常不受推荐。使用:retab