40

Vim跨行操作与Ex命令操作范围-Vim入门教程(46) | vim教程网

 4 years ago
source link: https://vimjc.com/vim-operate-muliple-line.html?
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Vim跨行操作与Ex命令操作范围-Vim入门教程(46)

跨行操作是日常工作中经常遇到的场景,最近在知乎上看到一个很好的讲解Vim跨行操作的案例,借鉴过来聊聊Vim的跨行操作。

简单来说,跨行操作是指一个Vim命令能同时操作多个文件行。在讲解跨行操作的具体案例时,需要理解下Vim的操作范围,推荐阅读Vim教程网之前介绍的两篇文章:ex命令操作范围Vim操作范围、文件范围介绍

1. 跨行删除

假设有一段从百度贴吧复制下来的纯文本内容,基本格式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
1楼2016-08-04 20:24

举报 |
个人企业举报
垃圾信息举报

×_××
xxx
3

Vim教程网挺不错的,支持下


2楼2016-08-05 02:33

举报 |
个人企业举报
垃圾信息举报

××××
xxxxxx
吧主
13

嗯不错,支持原创,以后会经常访问https://vimjc.com


3楼2016-08-05 12:18

举报 |
个人企业举报
垃圾信息举报

xxxxxxxx
l
1

支持原创,继续努力,妹子加油!

现在希望只把回帖内容保留下来,其他信息全部删掉,达到下面的效果:

1
2
3
4
5
Vim教程网挺不错的,支持下

嗯不错,支持原创,以后会经常访问https://vimjc.com

支持原创,继续努力,妹子加油!

可以看到,作为起始部分的 楼层信息 格式是固定的,而作为结束部分的 头衔等级、空行 也是固定的。因此,可以用Vim pattern 匹配到 起始结束 的部分,绕开难以处理的用户名和贴吧头衔等内容。

1.1 使用substitute命令替换非目标数据

对于起始部分的 楼层信息,可以通过简单的正则表达式 ^\d\+楼.* 进行匹配;同样地,结束部分的 头衔等级和空行 也可以通过正则表达式 ^\d\+\n^$\n 进行匹配。但是,楼层信息和头衔等级中间的多行内容,很难用简单的正则表达式进行匹配。

对于正则表达式来说,元字符组合 .* 可以匹配到行内所有内容,却唯独不包括行尾字符,也就是说,.* 默认情况下是不匹配换行符的。所以,如果需要匹配起始行到结束行中间的任意多行,用 .* 无法实现。

为了匹配起始行和结束行中间的全部内容,需要使用 \_.\{-}

\_. 可以匹配到行尾字符,又因为 * 是贪婪匹配的,默认会匹配到最远的结束行,因此用 \{-} 指定作最少的匹配,保证匹配到的是最近的结束行。

所以,匹配上述起始部分和结尾部分所有内容的正则表达式为 ^\d\+楼\_.\{-}\n^\d\+\n^$\n,使用substitute命令替换非目标数据的最终命令为 :%s/^\d\+楼\_.\{-}\n^\d\+\n^$\n//g

为了更加清楚地理解上述命令的含义,将上面的substitute替换命令拆分为 /^\d\+楼\_.\{-}\n^\d\+\n^$\n:%s///g 两条命令。执行效果如下图所示。

vim跨行删除
1.2 使用global命令删除非目标数据

当然,有了1.1介绍的起始部分和结束部分的正则表达式,配合之前介绍的Ex命令通过模式指定操作范围global 命令的执行原理,我们可以用 Vim 命令 :g/^\d\+楼/,/^\d\+\n^$\n/d 达到与 1.1 相同的操作效果。

上述 global 命令的含义是:在全文范围内 (缺省 %) 匹配 ^\d\+楼 并标记每一行匹配结果,然后在每一行匹配文本上逐行执行命令 ,/^\d\+\n^$\n/d,从而删除了起始部分和结束部分之间的所有内容。

:这里 global 执行的命令使用了Ex命令 delete 的range形式,,/^\d\+\n^$\n/d 实际上等价于 .,/^\d\+\n^$\n/d,表示删除(d)当前行 (.) 到 匹配模式 /^\d\+\n^$\n/ 之间的所有行。

2. 跨行分离

有了1.2介绍的基础,通过Vim寄存器可将匹配模式的内容删除到某个寄存器中,从而实现跨行分离操作。

例如,:g/^\d\+楼/,/^\d\+\n^$\n/d A 将开始部分和结束部分中间的内容删除并保存到寄存器 a 中,并且是对寄存器内容进行追加 (因为使用了 A 形式)。

同样地,:g/^\d\+楼/,/^\d\+\n^$\n/m$ 可将开始部分和结束部分中间的内容依次移动到当前文档的末尾 (通过 move 命令实现,具体可参考Vim移动命令move)。

vim跨行分离
qrcode.jpg

《女程序员说》

原创不易,希望能给小女子的公众号加个关注~


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK