目录

3. 奇偶行分离

** 本篇命令 **:g/^/m$ 最简单的方式,奇偶行将会分为连续的两组,适用于临时需要的手 动操作。应用时要确保正文后面不为奇数空行。let @a="" 把寄存器 a 清空,以使用下述命令。你也可以使用其他不同寄存 器。但如果你要把内容*自动*放到剪贴板,情况就会比较复杂,更 适合通过脚本来操作。这会在正文稍微提及。:g/^/+d A 把偶行删除并贮存到寄存器 a 中。使用时需要把内容从寄存器 a 中提取出来。:g/^/d A|m. 把奇数行存在寄存器 a 中。:%norm j"Add 把偶行删除并贮存到寄存器 a 中。:%norm jk"Add 把奇行删除并贮存到寄存器 a 中。:g/^/y A|+m. 一个无损的方法,只是把奇数行复制到寄存器 a 中。:g/^/+y A|+m. 只是复制偶数行到寄存器 a 中。:let @+=@a 把寄存器内容放到剪贴板。** 本篇帮助 **:h :y:h :registers:h copy-move:h let:h let-@:h quote_alpha:h quotestar:h quoteplus

这一篇,通过前面两篇基础的积累,我们可以来进行更复杂的操作——分离奇偶行。

奇偶行的分离,顾名思义,就是把奇数行的内容和偶数行的内容分离开来,方便我们分别利用。通过前面的知识,实际上我们也能够用删除的方法,分别保留奇数行和偶数行的内容,以达到同样的目的。但是,这种方法终究是不够直接的曲线救国,所以在这一章,我们就来看看有什么方法,可以一次性的把奇偶行分离开来。

3.1 基本操作

事不宜迟,让我们来看看这一篇要用到的实例,《圣经》中的一部分:

01| 1:1 起初神创造天地。02| 1:1 In the beginning God created the heaven and the earth.03| 1:2 地是空虚混沌。渊面黑暗。神的灵运行在水面上。04| 1:2 And the earth was without form, and void; and darkness was upon the face of the deep. And the Spirit of God moved upon the face of the waters.05| 1:3 神说,要有光,就有了光。06| 1:3 And God said, Let there be light: and there was light.07| 1:4 神看光是好的,就把光暗分开了。08| 1:4 And God saw the light, that it was good: and God divided the light from the darkness.09| 1:5 神称光为昼,称暗为夜。有晚上,有早晨,这是头一日。10| 1:5 And God called the light Day, and the darkness he called Night. And the evening and the morning were the first day.11| 1:6 神说,诸水之间要有空气,将水分为上下。12| 1:6 And God said, Let there be a firmament in the midst of the waters, and let it divide the waters from the waters.13| 1:7 神就造出空气,将空气以下的水,空气以上的水分开了。事就这样成了。14| 1:7 And God made the firmament, and divided the waters which were under the firmament from the waters which were above the firmament: and it was so.

这是奇偶行文本的一种典型例子:双语对照文本。在学习、练习翻译之类的需求中,我们会希望把中英内容分离开来。

我们可以有一个极简单的方法:

:g/^/+m$

可以得到如下文本:

01| 1:1 起初神创造天地。02| 1:2 地是空虚混沌。渊面黑暗。神的灵运行在水面上。03| 1:3 神说,要有光,就有了光。04| 1:4 神看光是好的,就把光暗分开了。05| 1:5 神称光为昼,称暗为夜。有晚上,有早晨,这是头一日。06| 1:6 神说,诸水之间要有空气,将水分为上下。07| 1:7 神就造出空气,将空气以下的水,空气以上的水分开了。事就这样成了。08| 1:1 In the beginning God created the heaven and the earth.09| 1:2 And the earth was without form, and void; and darkness was upon the face of the deep. And the Spirit of God moved upon the face of the waters.10| 1:3 And God said, Let there be light: and there was light.11| 1:4 And God saw the light, that it was good: and God divided the light from the darkness.12| 1:5 And God called the light Day, and the darkness he called Night. And the evening and the morning were the first day.13| 1:6 And God said, Let there be a firmament in the midst of the waters, and let it divide the waters from the waters.14| 1:7 And God made the firmament, and divided the waters which were under the firmament from the waters which were above the firmament: and it was so.

英文和中文的部分分离开来了。那么这个命令是如何生效的呢?

+m$ 命令是把 global 命令所在行的下一行移动到最后一行, 因此当 global 命令在第一行运行的时候,第二行的英文就会移动到最后一行,原本第三行的中文成为新的第二行。global 命令执行到新的第二行的时候,就会把新的第三行的英文又移动到最后一行。

所以到了最后,中英文就会全部分开。

在开篇中,我提到了这个命令使用时要注意正文后不能有奇数空行,道理很简单,因为空行是会被执行的,所以执行到最后一个奇数空行的时候,奇数空行的下一行正好就是偶数文本的第一行。这样偶数文本第一行就会被移到最后去了。

假如原本的文本中最后一行是空行,● 位置就是 global 正在执行的位置,09 行正好是原本偶数行的第一行。此时 global 执行 +m$ 命令,09 行就会被移动到15 行去 01| 1:1 起初神创造天地。 02| 1:2 地是空虚混沌。渊面黑暗。神的灵运行在水面上。 03| 1:3 神说,要有光,就有了光。 04| 1:4 神看光是好的,就把光暗分开了。 05| 1:5 神称光为昼,称暗为夜。有晚上,有早晨,这是头一日。 06| 1:6 神说,诸水之间要有空气,将水分为上下。 07| 1:7 神就造出空气,将空气以下的水,空气以上的水分开了。事就这样成了。● 08| 09| 1:1 In the beginning God created the heaven and the earth. 10| 1:2 And the earth was without form, and void; and darkness was upon the face of the deep. And the Spirit of God moved upon the face of the waters. 11| 1:3 And God said, Let there be light: and there was light. 12| 1:4 And God saw the light, that it was good: and God divided the light from the darkness. 13| 1:5 And God called the light Day, and the darkness he called Night. And the evening and the morning were the first day. 14| 1:6 And God said, Let there be a firmament in the midst of the waters, and let it divide the waters from the waters. 15| 1:7 And God made the firmament, and divided the waters which were under the firmament from the waters which were above the firmament: and it was so.

当然,利用这点,我们也能作出更好的奇偶行分离。

在上面的例子中,分离了的中英文内容是紧贴在一起的,这样对于下一步的操作很不方便。有没有办法在中英文内容中间加个空行呢?那就是在操作前,给文本末尾加上两个空行。如果要在中间插两个空行,那就加上四个空行。

原理很简单,奇数的空行会让文本内容发生我们不希望的移位,但如果是偶数的空行,那么发生移位的就只会是空行而已,并不会影响到文本内容。

如果你已经对 global 命令比较熟练,那么也很容易能够设计出这样的命令,完全不受文末空行的影响:

:g/^\S/+m$

奇偶行内容分开之后,就可以轻松选中目标内容,复制到剪贴板,再粘贴到需要的地方:

注意,下述操作适用于奇偶行文本有空行分隔的情况V}k"+y 标准操作 V}k 一些 GUI 版本 vim 中,支持 ctrl+c、cmd+c 之类的操作,或者你 可以自行设置快捷键绑定。

3.2 结合寄存器

3.2.1 寄存器入门

在第一篇中,我提到了 vim 的三个核心竞争力:ex 命令、寄存器和 vim language。ex 命令在上两篇已经演示了很多, vim language 就是用来写 vim 脚本的,这两者的威力不言而喻。但有的朋友会奇怪,为什么没有提到宏,很多 vim 的文章中都提到宏是 vim 的一个很强大的功能。其实只要各位看一下宏的帮助就明白了:

:h q

:h @

q{0-9a-zA-Z"} 在寄存器 {0-9a-zA-Z"} 里记录键入的字符 (大写名字的寄

存器表示附加键入的内容)。'q' 命令不能在执行寄存器时使

用。同样,在映射里也不能。

@{0-9a-z".=*} 执行寄存器 {0-9a-z".=*} 的内容 [count] 次。 注意 不

能用寄存器 '%' (当前文件名) 和 '#' (轮换文件名)。

"@="则会提示你输入一个表达式。这个表达式的结果会被执行。

因此,宏仅仅是寄存器的一种应用而已,我们不光可以通过 q 命令记录操作到寄存器,还可以直接为寄存器赋值,然后用 @ 命令来执行。

刚刚使用过的命令、函数、操作,也会记录到不同的寄存器,可以通过 @ 来重复执行。所以,知道宏的实质,了解寄存器,是让你的 vim 更强大的必经之路。

现在,就让我们来看看什么叫做寄存器。

所谓的寄存器,实际上就如其名,是一个用来贮存内容的容器。操作系统的剪贴板是一种寄存器,你复制了一段文字,这段文字就会放到剪贴板中,然后你就可以在不同的地方粘贴使用。

vim 的寄存器也有这样的基本功能,你可以把一堆字符通过删除、复制的方式放到寄存器中,然后在其他地方拿出来用。当然,vim 的寄存器和操作系统的剪贴板有很多不同的地方。

vim 总共有 9 种寄存器,各位可以通过帮助来详细了解,这里就不赘述。

:h registers

vim 的移动、删除和复制文本命令都能够配合寄存器使用。在 normal 模式下,可以通过半角双引号「 " 」来指定,而在 ex 命令中,则可以在命令后面使用(要以一个空格分隔)。比如 y 、d 、t 。

:h copy-move

本篇中,我们要用到的就是「命令寄存器」( a-zA-Z ):

:h quote_alpha

3.2.2 存入寄存器

上面的命令很简单,处理一些临时的需求很方便。但是,如果你需要在一些宏或者脚本中用到,上面的方法就显得啰嗦和麻烦了。通过寄存器,我们可以让这个操作一步到位——分离之后,就你可以把内容贴到你需要的地方了。

在开始之前,我们要先把命令寄存器清空:

:let @a="":h let-@

我们接下来要通过追加内容的方式来使用寄存器,如果寄存器中原本就有内容的话,就会污染我们的目标文本,所以清空寄存器是必须的。

下一步,我们把奇数行或偶数行的内容删除,并置入寄存器中 a 中:

:g/^/+d A:g/^/d A|m.

这两个命令各位应该很熟悉了,和我们删除奇偶行用的命令很相似,不同的地方只是在于,位于删除命令 d 的后面,有个大写字母 A,意思是把删除的内容追加到寄存器 a 中。

A 是 26 个命令寄存器之一,与 a 对应。实际上命令寄存器只有 a-z 这 26 个是可以被调用的,A-Z 的这些使用大写名字的寄存器,全部都和 a-z一一对应,表示把内容追加到寄存器。

比如下面这个命令

:g/^/+d a

意思是把每一行删除的内容都放到寄存器 a 里面,新的内容会覆盖掉旧的内容。而这条命令

:g/^/+d A

则是把删除掉的行追加到寄存器 a中,新的内容会跟在旧的内容后面,并不会覆盖旧的内容。

当提取寄存器内容时,调用 a 和调用 A 是没有差别的。各位可以在操作完成之后把寄存器 a中的内容粘贴出来看看差别。normal 模式下

"ap

"Ap

插入模式下

aA

而具备这种追加内容特性的就只有命令寄存器,其他寄存器都不具备追加功能。

同样地,我们可以通过 normal 命令来完成这个工作:

:%norm j"Add:%norm jk"Add

这两个命令和之前删除奇偶行的命令也几乎是一样的,仅仅是增加了「"A 」。A是命令寄存器,而 " 则是「指定寄存器」的意思,在 3.1 中已有说明。

上述的操作将会破坏原文档,如果我们只是希望提取出奇偶行的内容,那么就应该使用复制的方法:

:g/^/y A|+m. "把奇数行复制到寄存器 a 中:g/^/+y A|+m. "把偶数行复制到寄存器 a 中:h :y

这两条命令中使用了 y 代替 d ,这样原文档就不会被修改。但是,这样 global 命令就无法跳过不必要的行,所以添加了 m. 来移除非目标行的标记,这个技巧已在上一篇中有详细说明。

但是,这种需求就难以用 normal 命令来实现了。

3.2.3 提取寄存器

现在,我们已经把需要的文本放进了寄存器中。在 vim 内部,你有 3 种常用的方法来提取寄存器内容,适用于不同场景,分别是:

"ap normal 模式下粘贴寄存器内容,有多种变体,具体参照 :h p

a 插入模式下粘贴寄存器内容,参照 :h c_:put a 通过命令在指定行中插入寄存器内容,默认是当前行,参照 :h :put

上述 3 种方式都可以让你方便的在 vim 打开的文本中提取寄存器的内容,而且只要寄存器不清空,你在任何时候都能够取回其中的内容。

但是,这往往不能够满足我们的需求。我们提取的内容可能会希望粘贴到网上、word 中、笔记软件中,这个时候,就绕不开系统的粘贴板,或者叫剪贴板。

vim 中有两个寄存器和剪贴板相关,分别是 + 和 * ,称为「选择寄存器」。在不同的操作系统中(比如 Windows、Linux、OS X )这两个寄存器的运作会有不同。但是,在这里,我们不需要纠结它们技术上的差异,只需要知道哪个可以正常工作就行了(比如在 Windows 中,两者是等价的,根据我自己的测试,在 OSX 上也是一致的)。

有兴趣的朋友可以参照它们的帮助说明:

:h registers 参看第 7 点,选择寄存器 :h quotestar * 寄存器:h quoteplus + 寄存器

在接下来的讲解中,我会使用+寄存器,如果你发现这个寄存器无法正常运作,可以改用*试试。

和命令寄存器不同,选择寄存器无法直接追加内容,每次把新的内容放入选择寄存器,旧的内容都会被覆盖。所以我们无法通过改造上面给出的方法,让目标内容直接放入选择寄存器。

这个问题有两个解决方案:把完成收集命令寄存器内容放到选择寄存器中;

通过变量和表达式在选择寄存器中追加内容。

方案 1 简单,只要一个很易懂的命令:

:let @+ = @a

有编程基础的朋友应该可以直接理解这条赋值语句,意思就是让寄存器 +的内容等于寄存器a 的内容。因为 + 会被 a 直接取代,所以不必事先进行清空。

方案 2 在这个需求中使用则显然过重了,这里仅列出来,供各位参考,在未来其他系列的文章中,我们也许就会用到这种方案。

:let @+="\n" 选择寄存器是无法清空的,它总与系统剪贴板同步,所以你需要用一 些替代掉系统剪贴板的旧内容,又不会干扰到稍后追加的内容,换行 符是个不错的选择。:g/^/let @+.=getline(".")|+m. 奇数行内容追加到剪贴板:g/^/let @+.=getline(line(".")+1)."\n"|+m. 偶数行内容追加到剪贴板:h let.= let 的一种简略写法,let a.=b 相当于 let a = a . b:h expr5 vim 表达式的语法说明,「 . 」在表达式中用于连接字符串:h getline() vim 内建函数,用于取得制定行号的行的内容:h line() vim 内建函数,用于取得指定位置的行号,可配合 getline 使用

那么,本篇的内容就到此告一段落,在下一篇中,我们将会开始了解 {pattern} 的相关内容。

本篇命令及帮助回顾

** 本篇命令 **:g/^/m$ 最简单的方式,奇偶行将会分为连续的两组,适用于临时需要的手 动操作。应用时要确保正文后面不为奇数空行。let @a="" 把寄存器 a 清空,以使用下述命令。你也可以使用其他不同寄存 器。但如果你要把内容*自动*放到剪贴板,情况就会比较复杂,更 适合通过脚本来操作。这会在正文稍微提及。:g/^/+d A 把偶行删除并贮存到寄存器 a 中。使用时需要把内容从寄存器 a 中提取出来。:g/^/d A|m. 把奇数行存在寄存器 a 中。:%norm j"Add 把偶行删除并贮存到寄存器 a 中。:%norm jk"Add 把奇行删除并贮存到寄存器 a 中。:g/^/y A|+m. 一个无损的方法,只是把奇数行复制到寄存器 a 中。:g/^/+y A|+m. 只是复制偶数行到寄存器 a 中。:let @+=@a 把寄存器内容放到剪贴板。** 本篇帮助 **:h :y:h :registers:h copy-move:h let:h let-@:h quote_alpha:h quotestar:h quoteplus

vim删除奇数行_Vim 对特定行处理常用方法(三):奇偶行分离(及寄存器入门)...相关推荐

  1. vim删除奇数行_如何用vim删除特定的偶数行?

    来个简单点的(概念简单,都是基本操作),不过执行速度比较慢,适合不太大的文件 Step 1: 打开行号 set nu Step 2: 移动到文件末尾 G Step 3: 如果最后一行就是偶数行,新增一 ...

  2. vim 删除当前词_VIM中常用的查找、替换、删除模式总结

    1,简单替换表达式 去掉所有的行尾空格: %s/\s\+$// 去掉所有的空白行: %s/\(\s*\n\)\+/\r/ 去掉所有的"//"注释: %s!\s*//.*!! 去掉所 ...

  3. vim 删除当前词_vim 可视话模式(即删除一列和多列)

    打开一个新窗口 最简单的打开新窗口的方法是 :split 它把一个窗口分成两个,光标留在上面的那个窗口中. 通过 Ctrl-w+方向键 来在窗口间切换 比如 Ctrl-ww 或 Ctrl-w Ctrl ...

  4. mysql行锁怎么读_MySQL锁(三)行锁:幻读是什么?如何解决幻读?

    概述 前面两篇文章介绍了MySQL的全局锁和表级锁,今天就介绍一下MySQL的行锁. MySQL的行锁是各个引擎内部实现的,不是所有的引擎支持行锁,例如MyISAM就不支持行锁. 不支持行锁就意味着在 ...

  5. vim删除多行_vim文本编辑器

    vim文本编辑器是我们使用最多的编辑工具,它类似于我们windows系统的记事本一样,有着强大的文本编辑能力,是Linux系统不可缺少的工具,也是我们初学Linux时必须要掌握的命令之一. 在学习vi ...

  6. vim 删除重复部分的行 vim 技巧

    随笔 - 65, 文章 - 139, 评论 - 0, 引用 - 0 vim 删除重复部分的行 vim 技巧 g/\%(^\1\>.*$\n\)\@<=\(\k\+\).*$/d 重复的部分 ...

  7. pandas删除数据行中的重复数据行、基于dataframe所有列删除重复行、基于特定数据列或者列的作何删除重复行、删除重复行并保留重复行中的最后一行、pandas删除所有重复行(不进行数据保留)

    pandas删除数据行中的重复数据行.基于dataframe所有列删除重复行.基于特定数据列或者列的作何删除重复行.删除重复行并保留重复行中的最后一行.pandas删除所有重复行(不进行数据保留) 目 ...

  8. Vim 删除不包含指定字符串的行及统计匹配个数

    Vim 删除不包含指定字符串的行及统计匹配个数 转载▼     Help :g/pattern/d 是找到pattern, 删之 :v/pattern/d 是找到非pattern, 删之 :%s/xx ...

  9. shell 删除奇数偶数行

    今天总结一个正则的东西匹配和替换的删除奇数行和偶数行来理解模式空间以及模式空间是如何保存.标记数据的 删除偶数行: %s/\(^.*$\)\n^.*$/\1/g 删除奇数行: %s/^.*$\n\(^ ...

最新文章

  1. 淘宝内部大量使用的开源系统监控工具
  2. 解决 VSCode 配置 tab 空格数 Dart 语言无效的问题
  3. 【ArcGIS微课1000例】0006:创建随机点(Create Random Points)
  4. 使用Open Liberty的开发模式最大程度地缩短周转时间
  5. php将word转txt,PHP如何将将word文件转为pdf
  6. 企业电力征信大数据价值挖掘与应用
  7. Docker拉取ZooKeeper镜像安装运行
  8. 软件工程导论复习知识点
  9. 魅族插了卡显示无服务器,魅族手机SD卡无法读取怎么办解决方案
  10. 产品经理应具备的能力(初中高级),产品经理岗位细分
  11. ILSVRC2015_DET.tar.gz下载地址
  12. jsp学习—虚拟主机
  13. 重新启动linux系统应使用 命令实现,在重新启动Linux系统的同时把内存中的信息写入硬盘,应使用哪个命令...
  14. YDOOK:Java: 获取 boolean Boolean 数据类型的默认值
  15. WDM 驱动程序开发
  16. 特征选择时 的 特征子集选择和特征评价
  17. android6.0.1隐藏功能,安卓6.0系统界面调谐器怎么使用?安卓6.0隐藏功能开启和使用方法[多图]...
  18. 通配符选择器/后代选择器(包含选择器)/选择器分组
  19. 26.Vue列表渲染中key的作用与原理(内含虚拟DOM的对比算法详解)
  20. 微软Windows 11正式发布!(文末送书)

热门文章

  1. WSL2安装、WSL2 GUI
  2. dobbo 什么时候流行_六一节来了!情歌一晃就老了争什么争离别的眼泪红尘情歌无缘的情人首首好听...
  3. WindowsServer操作系统安全
  4. 2023计算机毕业设计SSM最新选题之java农产品追溯系统设计与实现e59uz
  5. DVWA下载安装教程步骤
  6. php cve 2017 12933,18-017 (March 27, 2018)
  7. csgo修改换服务器吗,csgo怎么切换外服
  8. win7右下角音量控制图标、电池图标消失
  9. 5e怎么绑定一键跳投_想上班摸鱼?分享一款超好用软件,一键隐藏窗口,摸鱼一时爽,一直摸鱼一直爽!...
  10. 100 个网络基础知识看完,可以成半个网络高手