Vim搜索和更换可变行数

Vim搜索和更换可变行数,vim,Vim,我有一些文本,其中有两列和两行或更多行。第一列名称只打印一次。此后,后续行将保留为空,直到再次更改为止 e、 g 我想更改以上内容以打印所有行中的列名,如下所示: name1 xxx name1 zza name1 yyy name1 zzz name2 ggg name2 xxx name3 xxx name3 zza name3 ggg name3 yyy name3 zzz 注:如前所述,第一列为空白的行数是可变的。可以是2以上的任意数字 如果重复应用,以下模式将起作用: :%s/\

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

e、 g

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

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/
但当然,这一次只会更改一行,我必须重复它,直到所有匹配项都更新


我的问题是:在行数可变的情况下,是否有一个命令来完成上述转换。

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

qq:%s/\(^\s\+\)\(.*\n\)\s\+/\1\2\1/
再次按回车键和q键停止录制宏


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

为此使用
awk
可以是一种解决方案:

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

您的模式几乎正常工作,主要问题是 替换换行符这会更改换行符,这就是为什么您需要 如您所述,运行多次。当您删除下一行时 光标将跳转它(即使它被替换回),然后 不能匹配

您可以通过仅在相关位置“开始”比赛来轻松解决此问题 部分,带有非常有用的标志。问题是 也有助于使模式更具可读性,控制魔术 选项这应该起作用:

:%s/^\v(\S+\s+).*\n\zs\s+/\1 
它捕获非空白零件,移动到下一个空白行开始和结束 在那里举行比赛。然后替换为捕获的零件。现在当 光标移动时,该过程将重复,如果出现以下行 不开始空白(例如在新组的开头)则
因为不匹配,所以不会发生任何事情。

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

col.py

#!/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 col.py < text.txt
python col.py

ViM可以使用Python支持进行编译,因此类似的内容可能会在ViM中使用。

可以指定要操作的行号,而不是“%”。例:
:12,16s/toto/titi/g
4@q将修正问题中的示例。同样,拥有一个像这样高的数字也没有坏处1000@q. 它仍然可以做你想要的。谢谢。我使用宏反复发出命令。有关单个命令,请参见sidyll应答。
python col.py < text.txt