;
)的线连接在一起,但是当使用g/;/j
时,除非多次调用,否则它无法按预期工作。例如以下内容:
a
1;
2;
3;
4;
5;
b
6;
7;
8;
9;
c
使用时:
:g/;/j
输出为:a
1; 2;
3; 4;
5; b
6; 7;
8; 9;
c
或
:g/;/-j
给出:a 1; 2; 3; 4; 5;
b 6; 7; 8; 9;
c
与
:g/;\_.\{-};/j
相似。我的预期输出是:
a
1; 2; 3; 4; 5;
b
6; 7; 8; 9;
c
或类似的东西,所以包含该模式的所有行都连接在一起。
如何实现?
#1 楼
问题的可能解释我认为
:g/;/j
不起作用的原因是因为:g
命令使用2-pass算法运行:第一次遍历时,它标记包含模式
;
的行,第二遍遍在标记的行上操作
在第二遍过程中,
:g
将1;
与2;
行连接在第一次通过时标记了1;
。但是我怀疑(不确定)它不与
1; 2;
加入3;
,因为2;
行已经不存在,其内容已与1;
行合并已处理。 因此,
:g
查找在第一遍(3;
)期间标记的下一行,并将其与下一个(4;
)连接起来。问题再次发生后,由于行3; 4;
不再存在,因此无法将5;
与4;
连接起来。解决方案1(带有vimscript)
也许您可以调用每当发现包含
;
的行时都要检查该函数,以检查前一行是否也包含分号:function! JoinLines()
if getline(line('.')-1) =~ ';'
.-1join
endif
endfunction
然后使用以下全局命令:
:g/;/call JoinLines()
或不带功能:
:g/;/if getline(line('.')-1) =~ ';' | -j | endif
解决方案2(无vimscript) />
每当全局命令
:g
找到模式;
时,它就会执行命令:.,/^[^;]*$/-1j
它可以像这样分解:
位置:
:g/;/.,/^[^;]*$/-1j
b
可以进一步细分,例如:是Ex命令j
的缩写形式,与大多数其他Ex命令一样,可以在其前面加上范围。此处的范围之前:
:join
(.,/^[^;]*$/-1
)范围遵循
a,b
的形式,其中a,b
和a
通常是2行号,并且允许您在行号介于b
和a
之间的一组行上进行操作,而不仅仅是一个。 因此,
b
命令将当前行(j
)和下一个不包含任何分号减一个(a
)的行之间的所有行连接起来。有关信息,请参见::g/pattern/a,bj
#2 楼
我一直通过全局搜索进行类似的联接并替换:s/;\n/;/
我不确定为什么,但是如果要插入新行,则必须使用
\n
评论
仅s仅适用于一行,要使其成为全局行,您需要使用%s,但随后它将连接几乎所有行,包括non;线
– Kenorb
16年1月1日在20:39
@kenorb嗯,不,我认为您可以完全根据需要使用:s命令。我认为这%s /; \ n \(。*; \)\ @ = /; /可以满足您的需求。
–克里斯蒂安·布拉班特(Christian Brabandt)
16年1月1日在21:01
@Christian Brabandt您的解决方案%s /; \ n \(。*; \)\ @ = /; /可以正常工作,但是\ @ =是什么?
–马克
20年6月19日在16:19
@Mark我刚刚将您的答案转换为评论;在这样做时,我想指出的是,您可以使用:help以及几乎所有内容来获取更多建议。即使是简单的:help也非常有用。
– D. Ben Knoble♦
20年6月19日在19:36
评论
FWIW,:g /; / j不起作用,因为它要分两次完成:首先扫描缓冲区,然后将命令应用于匹配的行。