Vim在递减时从某些数字前面删除零:
如果我带有以下文本文件:
a02
a03
a04
a05
a06
a07
a08
a09
a10
a11
使用ctrl+V
突出显示第二列和第三列,然后点击ctrl+X
递减,我留下:
a01
a02
a03
a04
a05
a06
a7
a8
a9
a10
我正在运行Vim版本7.4.1689并且我在没有我的.vimrc的情况下通过
加载它$ vim -u NONE
答案 0 :(得分:6)
这是因为Vim会自动识别并转换八进制值。
来自帮助(:h variables
):
从数字转换为字符串是通过使用ASCII表示 号码。
示例:
Number 123 --> String "123" Number 0 --> String "0" Number -1 --> String "-1"
将字符串转换为数字是通过将第一个数字转换为 一个号码。十六进制" 0xf9",八进制" 017"和二进制" 0b10"编号是 认可。如果字符串不以数字开头,则结果为零。
示例:
String "456" --> Number 456 String "6bar" --> Number 6 String "foo" --> Number 0 String "0xf1" --> Number 241 String "0100" --> Number 64 String "0b101" --> Number 5 String "-8" --> Number -8 String "+8" --> Number 0
您的值02
到07
被识别为有效八进制值并保留为原样,通过01
递减到八进制06
。
当您到达08
时,它不是有效的八进制值。它被视为字符串08
,转换为十进制值8
,并递减为7
。 09
再次发生这种情况,最终为8
。
10
和11
值也会递减为十进制。由于10
是十进制的,而不是八进制,因此您在结果0
值中无法获得前导9
。
我不知道如何通过递减命令来做你想做的事。
编辑:在找到this answer之后,我测试了这个表达式,它会在这个特定情况下执行您要执行的操作:
:%s/\v[0-9]+/\=printf("%02d", substitute(submatch(0), '^0\+', '', 0)-1)/
我不确定这是否解决了您的一般用例,因为它与使用选择的原始操作完全不同。但对于您提供的文件,它可以实现您所追求的结果。
解释一下解释一下:
首先,我们首先调用全局子命令%s
并传递\v
标志以启用"非常神奇的"模式。这可能会也可能不会根据您的设置更改行为,但这是一个公开示例,因此它包含在此处以确保模式处于活动状态。
:%s/\v
然后,我们找到所有连续的数字序列。这将从您的示例中找到02
,03
等。
[0-9]+
然后在替换部分,我们有了这个命令,它完成了真正的工作:
\=printf("%02d", substitute(submatch(0), '^0\+', '', 0)-1)
substitute()
函数确定新值是什么。 submatch(0)
表示使用整场比赛。使用^0\+
的模式和替换(空字符串)表示从任何具有一个的数字中去除前导零。最后的0
并不重要;它只是说substitute()
函数没有标志。
substitute
命令的结果是一个数字。说02
已被删除为2
。使用最后的- 1
,我们从该结果中减去1(减量)。
最后,此结果将传递给printf
函数。使用格式字符串%02d
表示以2位宽格式打印十进制值,使用前导零填充。
答案 1 :(得分:3)
如果您希望Vim将所有数字视为小数,您可能需要将以下行添加到.vimrc中:
set nrformats=