Vim - 在不改变列宽的情况下增加数字

Vim - Increase number without changing column width

我正在处理固定宽度的文件格式,我需要增加某些列中的所有数字。我有一个简单的宏,它向数字添加一个值,移动到下一行并重复(如 2aj)但是,这些数字从 1 开始,通常结束于 10000 以上,因此列宽变得混乱,例如(下划线为spaces,本例仅涵盖从9到10的跳转)

FOO_7_BAR
FOO_8_BAR
FOO_9_BAR

变成

FOO_9BAR
FOO_10_BAR
FOO_11_BAR

(注意新的文本栏会破坏我的程序)

当我需要的时候

FOO_9_BAR
FOO10_BAR
FOO11_BAR

我一直在手动检查并从前 9 列中删除 space,然后是 90 列,然后是 900 列,但我正在寻找一种更可靠的方法来处理这个问题而不处理前 10 列, 100、1000 等,使用不同的宏或任何手动输入。

谢谢。

我是这样想的,我觉得动画本身就说明了:

最后的结果是:

FOO 3 BAR
FOO 4 BAR
FOO 5 BAR
FOO 6 BAR
FOO 7 BAR
FOO 8 BAR
FOO 9 BAR
FOO10 BAR
FOO11 BAR

这需要一些手动操作,但仍然比手动删除空格要好。

不过,您也可以通过 Vimscript 编写一个自动执行此操作的函数!

首先,找出最短线的长度。你可以通过 ex 做到这一点。 :echo col("$") 在最短的线上。

然后,运行以下命令:

:g/.\{NUM\}/exec "norm! /[0-9]\<cr>X"

将上面命令中的 NUM 替换为您在上一步中得到的原始数字。

以下是其工作原理的解释:

:g/.\{NUM\}/    Find lines that are too long
exec "norm!     A common idiom: build a string to execute in normal mode
/[0-9]<cr>      Find the first number on the line
X               Delete the space before it (equivalent to "hx")

然后简单地重复运行同样的命令(你可以按:Up Return) 直到所有行的长度都相同——一旦出现这种情况就会导致错误(因为它不会找到任何匹配的行)。

这是整个过程的简短动画:

这可以用 :s 和一个子替换表达式来完成。

:%s/\v([^0-9]*)(\d+)/\=strpart(submatch(1), 0, 5 - len(submatch(2))).submatch(2)

我们的想法是捕获数字之前的部分和数字本身。替换通过 \= 执行 vim 表达式,将两个捕获组重新组合在一起。但是,通过 strpart() 将第一个捕获组切片为固定宽度(本例中为 5)减去第二个捕获组的长度 len(submatch(2)).

如需更多帮助,请参阅:

:h sub-replace-expression
:h strpart()
:h len()