Vim搜索并替换可变数量的行

时间:2017-02-15 12:00:27

标签: vim

我有一些文本,其中有两列和两行或更多行。第一列名称仅打印一次。此后,对于后续行,它将留空,直到再次更改为止。

e.g。

name1 xxx 
      zza 
      yyy
      zzz
name2 ggg
      xxx
name3 xxx
      zza
      ggg
      yyy
      zzz

我想更改上面的内容以在所有行中打印列名,如下所示:

name1 xxx 
name1 zza 
name1 yyy
name1 zzz
name2 ggg
name2 xxx
name3 xxx
name3 zza
name3 ggg
name3 yyy
name3 zzz

注意:如开头所述,第一列的空白行数是可变的。可以是2以上的任何数字。

如果重复应用,以下模式将起作用:

:%s/\(^\S\+ \)\(.*\n\)\s\+/\1\2\1/

但是,当然,这一次只会改变一行,我必须重复它,直到更新所有匹配。

我的问题:是否有一个命令可以完成上述转换,其中行数是可变的。

4 个答案:

答案 0 :(得分:1)

你的模式几乎正常工作,主要问题在于你 替换换行符,这会更改行,这就是您需要的原因 如您所述,多次运行。当你删除下一行时, 光标将跳转它(即使它被替换回来)然后你 无法比拟。

您可以通过仅在相关位置“开始”匹配来轻松解决此问题 部分,\zs标志非常有用。 \v是。{ 也有助于使模式更具可读性,控制魔力 选项。这应该有效:

:%s/^\v(\S+\s+).*\n\zs\s+/\1 

它捕获非空白部分,移动到下一个空行开始和 在那里设置匹配。然后替换为捕获的部分。现在的时候了 光标移动,过程将重复,如果以下行 不会开始空白(例如在新组的开头) 没有任何反应,因为它不匹配。

答案 1 :(得分:0)

您可以将相同的逻辑录制到宏,在本例中为q。

qq:%s/\(^\S\+ \)\(.*\n\)\s\+/\1\2\1/按返回并再次按q以停止录制宏

@q将运行一次,但如果您知道最大行数(例如:10),则可以运行10 @ q

答案 2 :(得分:0)

使用awk可以解决这个问题:

:%!awk '{if($2==""){$2=$1;$1=name}else{name=$1};print}'

答案 3 :(得分:0)

如果所有空格都是空格而不是制表符,您可以使用这个小Python脚本解决它:

<强> col.py

onServerError

然后将文本文件传递给脚本:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import fileinput

for line in fileinput.input():
    if not line.startswith(" "):
            current = line.split()[0]
            print(line, end="")
            continue
    print(line.replace(" " * len(current), current, 1), end="")

可以使用Python支持编译ViM,因此可以在ViM中使用此类内容。