我已经查看了有关Stack Overflow的几个问题,以了解如何在不查找所需内容的情况下将空格转换为制表符。关于如何将制表符转换为空格,似乎还有更多问题,但我正尝试相反的做法。
在Vim
我尝试过的过程中:retab
,:retab!
没有运气,但我相信这些实际上是为了从制表符转到空格。
我在命令提示符下都尝试了两次expand
,unexpand
但没有任何运气。
这是有问题的文件:
如何使用或Shell 将前导空格转换为制表符Vim
?
我已经查看了有关Stack Overflow的几个问题,以了解如何在不查找所需内容的情况下将空格转换为制表符。关于如何将制表符转换为空格,似乎还有更多问题,但我正尝试相反的做法。
在Vim
我尝试过的过程中:retab
,:retab!
没有运气,但我相信这些实际上是为了从制表符转到空格。
我在命令提示符下都尝试了两次expand
,unexpand
但没有任何运气。
这是有问题的文件:
如何使用或Shell 将前导空格转换为制表符Vim
?
Answers:
使用Vim扩展所有前导空格(大于'tabstop'
),您可以使用,retab
但首先要确保'expandtab'
已重置(:verbose set ts? et?
是您的朋友)。retab
需要一个range,所以我通常指定%
要表示“整个文件”。
:set tabstop=2 " To match the sample file
:set noexpandtab " Use tabs, not spaces
:%retab! " Retabulate the whole file
在进行此类操作(尤其是使用Python文件!)之前,我通常先进行设置'list'
,以便可以看到空白并进行更改。
我在下面的映射我.vimrc
这个:
nnoremap <F2> :<C-U>setlocal lcs=tab:>-,trail:-,eol:$ list! list? <CR>
:set noet
,:set tabstop=2
,:retab!
,:%retab!
,:set tabstop=1
,:retab!
,:%retab!
%
。F2映射与输入的完全相同。
:set noet ts=2 |%retab!
:%retab!
仍然有效。我与混淆==
,等等,它确实遵守了keepindent设置。
:set tabstop=4
1-如果您有空格并需要制表符。
首先,您需要确定一个标签中有多少空格。就是说,假设您的行首4个空格,即8个。现在,有了该信息,您可以:
:set ts=4
:set noet
:%retab!
这里有问题!此命令序列将查找您的所有文本,而不仅仅是行首。那意味着一个字符串,如:"Hey,␣this␣␣␣␣is␣4␣spaces"
将变为"Hey,␣this⇥is␣4␣spaces"
,但不是!它的一个标签!
为了解决这个小问题,我建议使用a search
代替retab
。
:%s/^\(^I*\)␣␣␣␣/\1^I/g
此搜索将在整个文件中查找任何行,这些行以任意数量的选项卡开头,后跟4个空格,并用找到的任意数量的选项卡加一个代替。
不幸的是,这不会立即运行!
首先,文件将包含以空格开头的行。然后,搜索将仅将前4个空格转换为选项卡,并让以下内容...
您需要重复该命令。多少次?直到你得到一个pattern not found
。我还没有想到一种使过程自动化的方法。但是,如果您这样做:
`10@:`
您可能已经完成了。此命令将上一次搜索/替换重复10次。您的程序不太可能有那么多缩进。如果有,请再次重复@@
。
现在,只需完成答案即可。我知道您要求相反,但您永远不知道何时需要撤消操作。
2-您有制表符并需要空格。
首先,确定要将选项卡转换为多少空格。假设您希望每个标签为2个空格。然后执行以下操作:
:set ts=2
:set et
:%retab!
字符串也会有同样的问题。但是,由于它的更好的编程风格是不在字符串中使用硬标签,因此您实际上在这里做得很好。如果您确实需要在字符串内使用制表符,请使用\t
。
ex command
,因为这将是函数内部的内容。不,它并不罕见。您只需要使用带空格的字符串就可以避免混乱。一点也不罕见。我去过那里 感谢您的评论。
^
符号,要从该行的开头开始搜索,则可能会更改字符串中的空格。使用,^
可以保证自行开始以来仅更改空格和制表符,因此缩进。除此之外,如果您确定可以一次完成所有操作,请删除^
并仅运行一次::%s/\(^I*\)␣␣␣␣/\1^I/g
:%s/\(^\s*\)\@<= /\t/g
翻译:搜索4个连续空格的每个实例(在=字符之后),但仅当到达该点的整行是空格(使用零宽度后向断言,\@<=
)时才进行搜索。用制表符替换每个找到的实例。
:%s/\(^\s*\)\@<= /\t/g
-在<=
unexpand
(和expand
)这是一个非常好的解决方案:https : //stackoverflow.com/a/11094620/1115187,主要是因为它使用了* nix-utilities:
我的原始答案
Bash片段,用文件夹中所有文件中的选项卡(递归)替换4个空格的缩进({4}
脚本中有两个):.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下测试
如果您已安装GNU coreutils,请考虑%!unexpand --first-only
或对于4个空格选项卡,请考虑%!unexpand -t 4 --first-only
(--first-only
存在,以防您不小心调用unexpand
了--all
)。
请注意,这将仅替换指定的制表位之前的空格,而不替换其后的空格;除非您更真实地显示选项卡,否则您不会在vim中看到视觉差异。例如,我的~/.vimrc
容器set list listchars=tab:▸┈
(我怀疑这就是您认为unexpand
不起作用的原因)。
要使用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模式下运行vim(-e
执行给定ex命令(实际上是几个命令)的每个文件上,),以将现有的前导空格更改为制表符,重置制表符停止位并将制表符改回空格,最后保存并退出。
在ex模式下运行可防止此情况:Vim: Warning: Input is not from a terminal
对于每个文件。
简单的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()
sed "s/ +/`echo -e '\t'`/g" < input.py > output.py
)似乎是转换所有空格,而不仅仅是前导空格。在第二个示例(sed "s/^ +/`echo -e '\t'`/g" < input.py > output.py
)中,它仅用制表符替换每行的第一个空格,并保留其余的行。