如何在Vim或Linux中将空格转换为制表符?

时间:2012-02-01 23:02:22

标签: linux vim tabs spaces

我已经查看了有关Stack Overflow的几个问题,了解如何在不查找我需要的情况下将空格转换为制表符。似乎有更多关于如何将标签转换为空格的问题,但我正试图做相反的事情。

Vim {I}我试过:retab:retab!但没有运气,但我相信这些实际上是为了从标签转到空格。

我在命令提示符处尝试了expandunexpand而没有任何运气。

以下是相关文件:

http://gdata-python-client.googlecode.com/hg-history/a9ed9edefd61a0ba0e18c43e448472051821003a/samples/docs/docs_v3_example.py

如何使用Vim或shell将前导空格转换为标签?

8 个答案:

答案 0 :(得分:274)

使用Vim扩展所有主要空格(宽于'tabstop'),您使用retab是正确的,但首先要确保重置'expandtab'({{ 1}}是你的朋友)。 :verbose set ts? et?需要范围,因此我通常会将%指定为“整个文件”。

retab

在做这样的事情之前(特别是Python文件!),我通常会设置'list',这样我就可以看到空白并进行更改。

我在my .vimrc中有以下映射:

:set tabstop=2      " To match the sample file
:set noexpandtab    " Use tabs, not spaces
:%retab!            " Retabulate the whole file

答案 1 :(得分:30)

1 - 如果您有空格并想要标签。

首先,您需要确定一个标签有多少个空格。也就是说,假设您有前导4个空格的行,或者8 ...比您意识到您可能希望标签为4个空格。现在有了这些信息,你可以:

:set ts=4
:set noet
:%retab!

这里有一个问题!这一系列命令将查找所有文本,而不仅仅是行开头的空格。这意味着像"Hey,␣this␣␣␣␣is␣4␣spaces"这样的字符串将变为"Hey,␣this⇥is␣4␣spaces",但不是!它是一个标签!。

要解决这个小问题,我建议使用search,而不是retab

:%s/^\(^I*\)␣␣␣␣/\1^I/g

此搜索将在整个文件中查找以任意数量的标签开头的任何行,后跟4个空格,并将其替换为找到的任意数量的标签加上一个。

不幸的是,这不会立即运行!

首先,文件将以空格开头。然后搜索将仅将前4个空格转换为选项卡,并让以下内容...

您需要重复该命令。多少次?直到你得到pattern not found。我想不出一种方法来自动化这个过程。但如果你这样做:

`10@:`

你可能已经完成了。此命令重复上次搜索/替换10次。你的程序不太可能有这么多的缩进。如果有,请再次重复@@

现在,只是为了完成答案。我知道你要求相反,但你永远不知道什么时候需要撤消。

2 - 您有标签并想要空格。

首先,确定要将标签转换为多少个空格。假设您希望每个选项卡都是2个空格。然后你做:

:set ts=2
:set et
:%retab!

这会对字符串产生同样的问题。但是作为更好的编程风格,不使用字符串中的硬标签,你实际上在这里做了一件好事。如果您确实需要字符串中的选项卡,请使用\t

答案 2 :(得分:11)

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

翻译:搜索4个连续空格的每个实例(在=字符之后),但仅当整个行到达该点为空时(这使用零宽度后视断言,\@<=) 。用制表符替换每个找到的实例。

答案 3 :(得分:0)

用于替换 4 - 空格缩进(脚本中有两个{4})的Bash代码段,其中包含.py文件夹中所有./app文件中的标签(递归) ):

find ./app -iname '*.py' -type f \
    -exec awk -i inplace \
    '{ match($0, /^(( {4})*)(.*?)$/, arr); gsub(/ {4}/, "\t", arr[1]) }; { print arr[1] arr[3] }' {} \; 

不会在中间或末尾修改4个空格。

在Ubuntu 16.0x和Linux Mint 18下测试

答案 4 :(得分:0)

在我的情况下,我有多个空格(字段由一个或多个空格分隔),我想用制表符替换。做到了以下几点:

:% s/\s\+/\t/g

答案 5 :(得分:0)

如果您已安装GNU coreutils,请考虑使用%!unexpand --first-only或对于4位制表符,请考虑%!unexpand -t 4 --first-only--first-only存在,以防您不小心调用了unexpand --all)。

请注意,这只会替换指定的制表位之前的空格,不会后面的空格;除非您更真实地显示选项卡,否则您不会在vim中看到视觉差异。例如,我的~/.vimrc包含set list listchars=tab:▸┈(我怀疑这就是为什么您认为unexpand不起作用的原因。)

答案 6 :(得分:0)

要使用Vim重新设置一组文件(例如,目录层次结构中的所有* .ts文件)的大小写,请从2个空格改为4个空格,您可以在命令行中尝试以下操作:

find . -name '*.ts' -print0 | xargs -0 -n1 vim -e '+set ts=2 noet | retab! | set ts=4 et | retab | wq'

这是在使用find将所有匹配的文件传递到xargs(find上的-print0选项与xargs的-0选项一起使用,以便处理带有空格的文件。名称)。

xargs在执行给定ex命令(实际上是几个命令)的每个文件上以ex模式(-e)运行vim,以将现有的前导空格更改为制表符,重置制表符停止位并将制表符改回空格最后保存并退出。

在ex模式下运行可以防止此情况:每个文件Vim: Warning: Input is not from a terminal

答案 7 :(得分:-1)

简单的Python脚本:

import os

SOURCE_ROOT = "ROOT DIRECTORY - WILL CONVERT ALL UNDERNEATH"

for root, dirs, files in os.walk(SOURCE_ROOT):
    for f in files:
        fpath = os.path.join(root,f)
        assert os.path.exists(fpath)
        data = open(fpath, "r").read()
        data = data.replace("    ", "\t")
        outfile = open(fpath, "w")
        outfile.write(data)
        outfile.close()