Vim 中复制代码常用的一些正则表达式替换技巧

 
Category: Tips

写在前面

这次来写一个比较小的主题, 关于在 vim 中快速替换内容, 也算是精进一下 Vim 技巧了.

这里以复制别人博客文章中的代码为例, 如果有一键复制当然是最好的, 那没有的话就要手动复制了, 而这就会出现一个问题, 如果前面不巧含有行号之类的冗余信息呢? 这就需要自己手动删除了(下例), 由于 Vim 含有很多高级的宏操作, 下面来看看怎样快速解决这个问题. (并且给出以下举一反三的方法)

 1namespace A {
 2    // S2
 3    struct Base {};
 4}
 5
 6namespace M {
 7    // S3 not works!
 8    namespace B {
 9        // S1
10        struct Derived : A::Base {};
11    }
12}
13
14int main() {
15    M::B::Derived d;
16    f(d); // #1
17}

好像是源自 ISO C++ 的代码段

取巧的方法: 块选取

通过块选中然后删除

C-v
16j
x
.

这就体现出相对行号(relative number)的重要性了

但是不巧的是, 这个方法只适用于小函数(就是行数比较少的, 基本上一屏幕可以放得下的), 对于几百行的函数, 一页一页跳转其实并不方便(事先记录一下当然也可以)

使用正则替换

行首长度一致

这里给出一种通用的方法, 使用正则替换:

:1,17s/^..//g

语法的话就不多说了, 看看 Vim 文档或者书.

行首长度不一致

指定了替换范围, 这么一看是不是感觉块选取的方法要容易一些(:cry:), 但是没关系, 来看这种情况:

1namespace A {
2    // S2
3    struct Base {};
4}
5
6namespace M {
7    // S3 not works!
8    namespace B {
9        // S1
10        struct Derived : A::Base {};
11    }
12}
13
14int main() {
15    M::B::Derived d;
16    f(d); // #1
17}

这里就不能用块选取了, 而是要删除所有数字, 这要怎么做呢?

:1,17s/^\d*//g

就可以了, 还是很方便的.

出现其他字符

当然, 还有这样一种情况:

l1namespace A {
l2    // S2
l3    struct Base {};
l4}
L5
l6namespace M {
l7    // S3 not works!
l8    namespace B {
l9        // S1
L10        struct Derived : A::Base {};
l11    }
l12}
l13
l14int main() {
L15    M::B::Derived d;
l16    f(d); // #1
l17}

每隔五行出现一次大写字符, 这种情况也是得用正则来做:

:1,17s/^\w\d*//g