我在Stack Overflow上看了几个关于如何将空格转换为制表符而没有找到我需要的问题。关于如何将制表符转换为空格,似乎有更多的问题,但我正试图做相反的事情。

在Vim中,我尝试过:retab和:retab!没有运气,但我相信这些实际上是用来从制表符到空格的。

我在命令提示符下尝试了展开和取消展开,但没有任何运气。

以下是该文件:

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

如何使用Vim或shell将前导空格转换为制表符?


当前回答

使用Vim重新标签一组文件(例如,所有的*。从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模式(-e)对每个文件运行vim,执行给定的ex命令(实际上是几个命令),将现有的前导空格更改为制表符,重置制表位并将制表符更改为空格,最后保存并退出。

在ex模式下运行可以防止:Vim:警告:每个文件的输入不是来自一个终端。

其他回答

简单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()
:%s/\(^\s*\)\@<=    /\t/g

转换:搜索4个连续空格(在=字符之后)的每个实例,但前提是直到该点的整行都是空格(这使用了零宽度向后查找断言\@<=)。用制表符替换每个找到的实例。

使用Vim重新标签一组文件(例如,所有的*。从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模式(-e)对每个文件运行vim,执行给定的ex命令(实际上是几个命令),将现有的前导空格更改为制表符,重置制表位并将制表符更改为空格,最后保存并退出。

在ex模式下运行可以防止:Vim:警告:每个文件的输入不是来自一个终端。

1 -如果你有空格,想要制表符。

首先,您需要决定单个制表符将包含多少个空格。也就是说,假设你的行前导有4个空格,或者8…然后你会意识到制表符应该是4个空格。现在有了这些信息,你可以:

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

这里有个问题!这个命令序列将查找所有文本,而不仅仅是行首的空格。这意味着像“嘿,␣这个␣␣␣␣是␣4个␣空格”这样的字符串将变成“嘿,␣这个⇥是␣4个␣空格”,但它不是!这是账单!

为了解决这个小问题,我建议搜索,而不是重新标签。

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

这个搜索将在整个文件中查找以任意数量的制表符开始,后面跟着4个空格的任何行,并将其替换为它找到的任意数量的制表符加1。

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

首先,文件的行以空格开头。然后搜索将只转换前4个空格为制表符,并让下面的…

需要重复执行该命令。多少次?直到你找到一个没有发现的模式。我还想不出一个方法来自动化这个过程。但如果你这样做了:

`10@:`

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

现在,我们来完成这个答案。我知道你想要的恰恰相反,但你永远不知道什么时候需要挽回。

2 -你有制表符,想要空格。

首先,决定要将制表符转换为多少个空格。假设你想让每个制表符是2个空格。然后你要做:

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

字符串也会有同样的问题。但是在字符串中不使用硬制表符是更好的编程风格,你实际上在这里做了一件好事。如果确实需要字符串中的制表符,请使用\t。

在我的例子中,我有多个空格(字段由一个或多个空格分隔),我想用一个制表符替换它们。下面的人做到了:

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