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

cwd*_*cwd 172 linux vim tabs spaces

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

Vim我试过:retab:retab!没有运气,但我相信那些实际上是从标签反正要空间.

我试过两个,expandunexpand在命令提示符没有运气.

这是有问题的文件:

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

如何使用其中一个或shell 将前导空格转换为制表符Vim

Joh*_*web 286

使用Vim扩展所有前导空格(宽于'tabstop'),你是正确的使用,retab但首先确保'expandtab'重置(:verbose set ts? et?是你的朋友).retab需要一个范围,所以我通常指定%"整个文件".

:set tabstop=2      " To match the sample file
:set noexpandtab    " Use tabs, not spaces
:%retab!            " Retabulate the whole file
Run Code Online (Sandbox Code Playgroud)

在做这样的事情之前(尤其是Python文件!),我经常设置'list',以便我可以看到空白和更改.

我在下面的映射.vimrc这个:

nnoremap    <F2> :<C-U>setlocal lcs=tab:>-,trail:-,eol:$ list! list? <CR>
Run Code Online (Sandbox Code Playgroud)

  • 对于那个特定的文件,我只会这样做:`:set noet ts = 2 |%retab!` (7认同)
  • 这是我如何让它工作,不知道什么是必要的,什么不是,顺便说一下我不知道reatab之前的"%"是什么:`:set noet`,`:set tabstop = 2`,` :retab!`,`:%retab!`,`:set tabstop = 1`,`:retab!`,`:%retab!` (2认同)
  • 我已经更新了我的答案,以解释我为什么使用“%”。[F2 映射与其键入的完全一样](https://github.com/johnsyweb/dotfiles/blob/master/.vimrc#L324)。 (2认同)

Dr *_*eco 34

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

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

:set ts=4
:set noet
:%retab!
Run Code Online (Sandbox Code Playgroud)

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

为了解决这个小问题,我推荐了一个search,而不是retab.

:%s/^\(^I*\)????/\1^I/g
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

`10@:`
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

:set ts=2
:set et
:%retab!
Run Code Online (Sandbox Code Playgroud)

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


Sim*_*aun 12

:%s/\(^\s*\)\@<=    /\t/g
Run Code Online (Sandbox Code Playgroud)

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


小智 8

将所有空格更改为制表符 :%s/\s/\t/g


max*_*kov 6

Linux:与unexpand(和expand

这是一个非常好的解决方案:https : //stackoverflow.com/a/11094620/1115187,主要是因为它使用*nix-utilities:

  1. unexpand — 空格 -> 制表符
  2. 展开— 制表符 -> 空格

Linux:自定义脚本

我的原答案

用于在文件夹中的所有文件中用制表符替换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] }' {} \; 
Run Code Online (Sandbox Code Playgroud)

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

在 Ubuntu 16.0x 和 Linux Mint 18 下测试