我想在不使用它们的代码中使用制表符。到目前为止,我所做的实现制表符非常简单:
%s/^ /\t/g
%s/^\t /\t\t/g
..
问题:有没有办法用标签()替换两个空格(
\t
)在一行开头找到它的次数?
答案 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