Vim:将每行选择的第一个单词替换为列表中的数字

时间:2015-02-09 22:18:14

标签: vim

我有一个大文件,其中包含带有混乱数字的选项。它应该是一个序列1,2,3,......但是有几行被搞砸了。我想改变像

这样的东西
  

FOO

     

     

1 foobar

     

12345 foobar

     

6546458 foobar

     

4 foobar

  

FOO

     

     

1 foobar

     

2 foobar

     

3 foobar

     

4 foobar

我知道我可以使用类似3,$的内容来选择我关注的行和put = range(1,1000)来创建以我想要的数字开头的新行,但我想将这些数字放在当前的行上有数据,而不是新行。混乱的数字是几个字符长,但总是一个字。感谢。

3 个答案:

答案 0 :(得分:3)

执行以下操作:

:let i=1
:g/^\d\+/s//\=i/|let i=i+1

概述

设置一些变量(let i=1)作为我们的计数器。在以数字(:g/^\d\+/)开头的每一行上,我们执行替换(:s//\=i/)以使用我们的计数器(\=i)替换模式,然后递增计数器{{1} })。

为什么要使用let i=i+1?为什么不只是:g

您只需使用替换命令即可完成此操作,但子替换表达式:s需要一个表达式来计算值(请参阅\=)。由于:h sub-replace-expression是一个声明,因此无用。

有几种方法可以解决这个问题:

  • 创建一个增加变量然后将其返回的函数
  • 使用数组,然后更改内部数字(就地),然后将值返回数组。例如let i = i + 1
  • 如果每行只有1个替换,那么请执行上面的map(arr, 'v:val+1')[0]技巧

使用就地数组修改的完整示例:

:g

就个人而言,我会使用你能记住的任何方法。

更多帮助

:let i=[1]
:%s/^\d\+/\=map(i,'v:val+1')[0]

答案 1 :(得分:1)

/^\d\+\s  -- Searches for the first occurrence
ciw0<Esc> -- Replaces the word under cursor with "0"
yiw       -- Copies it
:g//norm viwp^Ayiw
          -- For each line that matches the last search pattern,
          --   Replace the current word with copied text,
          --   Increment it,
          --   Copy the new value.

<Esc>只是 Esc ^A输入为 Ctrl + V Ctrl + A

答案 2 :(得分:0)

您可以使用以下功能:

function Replace()
    let n = 1 
    for i in range(0, line('$'))
        if match(getline(i), '\v^\d+\s') > -1
            execute i . 's/\v^\d+/\=n/'
            let n = n + 1 
        endif
    endfor
endfunction

它遍历整个文件,检查每一行是否以数字后跟空格字符开头,并用计数器替换,每次更改都会增加。

称之为:

:call Replace()

在你的例子中产生:

foo
bar
1 foobar
2 foobar
3 foobar
4 foobar