行号列表作为vim的输入

时间:2018-11-29 14:33:23

标签: vim

我在文件中有一个行号列表,例如

1
5
3

我想向另一个文件中的每个行号添加相同的注释:

test1 # comment
test2 # comment
test3
test4
test5 # comment

有没有一种方法可以将文件逐行作为vim中行号的输入,并对其执行一些操作?我知道如何使用

定位单行
5,5s/$/ # comment/ 

但是我不知道如何从文件中获取行号到vim命令中。

4 个答案:

答案 0 :(得分:5)

您可以从文件创建Vim列表:

let list = readfile('path/to/list.txt')

或者如果文件已经在Vim中打开:

let list = getbufline('list.txt', 1, '$')

这会让您:

:echo list
['1', '5', '3']

第二步,我们需要找到适用的行。 for循环将完成;行号将通过:execute插入:

for l in list
    execute l . 's/$/ # comment/'
endfor

或者,我们可以将:global命令误用于迭代。不过,这要慢一些,对于index(),我们必须避免将苹果(此处:数字行)与橙子(此处:字符串)分别表示清单)。我仍然提到这一点,因为这更笼统。例如您可以使用它从文件到目标行读取单词或正则表达式:

global/^/if index(list, "" . line('.')) != -1 | s/$/ # comment/ | endif

答案 1 :(得分:4)

听起来像Awk的工作。

:%!gawk 'NR == FNR {a[$0] = " \#comment"; next} FNR in a { $0 = $0 a[FNR]} 1' lines.txt -

awk程序已扩展以提高可读性:

NR == FNR {
    a[$0] = " #comment";
    next
}

FNR in a {
    $0 = $0 a[FNR]
}

1

基本思想是我们将两个文件发送到awk中,分别为lines.txt和stdin(-)。我们在lines.txt文件中将行号存储在数组a中,并将注释作为值(a[$0] = " #comment";)。如果行号在我们的数组(stdin)内,则在经过FNR in a时更新行。然后打印出stdin1)的每一行

注意:我正在使用gawk,因此您的里程可能会有所不同。还必须转义,#,因为Vim会将其扩展到备用缓冲区。

答案 2 :(得分:3)

鉴于已完成列表的提取-请参阅Ingo的答案。

如果您没有太多的行和索引,则以下内容应该足够快(应该比:global解决方案更快)

:call setline(1, map(range(1, max(list)), 'index(list, v:val) >=0 ? printf("test%d # comment", v:val) : v:val'))

如果行数和索引数增加很多,我不确定此O(N²)解决方案是否会扩展。由于:for循环的速度很慢,因此我不确定使用现有工具可以如何高效地进行下去。

可能是:

:let d = {}
:call map(copy(list), 'extend(d, {v:val: printf("test%d # comment", v:val)})')
:call setline(1, map(range(1, max(list)), 'get(d, v:val, v:val)'))

这是绝对复杂的

以下是另一种复杂的O(N)方法

:call sort(list)
:call setline(1, map(range(1, slist[-1]), 'v:val == slist[0] ? printf("test%d # comment", remove(slist, 0)) : v:val'))

答案 3 :(得分:3)

您还可以使用生成的sed脚本:

sed 's:$:s/$/ # comment/:' line_nums | sed -f- infile

生成的脚本如下:

1s/$/ # comment/
5s/$/ # comment/
3s/$/ # comment/

第二个sed的输出如下所示:

test1 # comment
test2
test3 # comment
test4
test5 # comment