Vim实用技巧:global命令
:global
命令结合了Ex命令与Vim的模式匹配这两方面能力。凭借该命令,可以在某个指定模式的所有匹配行上运行Ex命令。就处理重复工作的效率而言,global
命令是除点范式以及宏之外,最为强大的Vim工具之一。
技巧98 认识global命令
:global
命令允许在某个指定模式的所有匹配行上运行Ex命令。首先研究一下它的语法。
:global
命令通常采用以下形式(参见 :h :g
)。
:[range] global[!] /{pattern}/ [cmd]
首先,在缺省情况下,:global
命令的作用范围是整个文件(%),这一点与其他大多数Ex命令(包括:delete
、:substitute
以及 :normal
)有所不同,这些命令的缺省范围仅为当前行(.)。
其次,{pattern}
域与查找历史相互关联。这意味着如果将该域留空的话,Vim会自动使用当前的查找模式。
另外,[cmd]
可以是除 :global
命令之外的任何Ex命令。在实际应用中,如表5-1中所列的那些Ex命令,无一不在处理文本过程中起到了极大的作用。顺便提一下,如果不指定任何 [cmd]
,Vim将缺省使用 :print
。
还有,可以用 :global!
或者 :vglobal
(v表示invert)反转:global
命令的行为。这两条命令将指示Vim在没有匹配到指定模式的行上执行 [cmd]
。在下一节中,将会分别看到 :global
与 :vglobal
的应用实例。
最后需要指出的是 :global
命令在指定 [range]
内的文本行上执行时通常分为两轮。第一轮,Vim在所有[pattern]
的匹配行上做上标记。第二轮,再在所有已标记的文本行上执行 [cmd]
。另外,由于 [cmd]
的范围可单独设定,因此可在多行文本段内进行操作,将在技巧101中讲解这项强大的技术。
技巧99 删除所有包含模式的文本行
将
:global
命令与:delete
命令一起组合使用,可以快速裁剪文件内容。对于那些匹配{pattern}
的文本行,既可以选择保留,也可以将其丢弃。
以下内容取自Vimcasts.org归档网页中有关前几部主题的链接。
global/episodes.html
<ol><li><a href="/episodes/show-invisibles/">Show invisibles</a></li><li><a href="/episodes/tabs-and-spaces/">Tabs and Spaces</a></li><li><a href="/episodes/whitespace-preferences-and-filetypes/">Whitespace preferences and filetypes</a></li>
</ol>
显而易见,所有列表项均由两部分数据构成:主题的标题及其URL。接下来,将利用 :global
命令分别取出这两组数据。
用 ':g/re/d' 删除所有的匹配行
如果只想保留 <a>
标签内的标题,而把其他行删掉,该怎么做呢?在本例中,由于每组链接的内容各占一行,而其他文本行只包含或开或闭这两种类型的标签,因此,如果设计一个可以匹配HTML标签的模式,再用它调用 :global
命令,就可以删掉所有该模式的匹配行了。
以下命令可以做到这一点。
➾ /\v\<\/?\w+>
➾ :g//d
如果在Vimcasts.org的归档文件中运行这两条命令,文件的内容将会变为:
Show invisibles
Tabs and Spaces
Whitespace preferences and filetypes
与 :substitute
命令类似,也可以将:global
命令的查找域留空。这样一来,Vim将会重用最后一次的查找模式(参见技巧91)。这意味着在构造正则表达式的过程中,可以先进行粗粒度匹配,然后再对其进行精细调整,正如技巧85展示的那样。
本例的正则表达式采用的是 very magic
模式(在技巧74中有所涉及)。首先,它会匹配左尖括号(\<
);然后,匹配可选的正斜杠(\/?
);接下来,再匹配一个或多个单词型字符(\w+
);最后匹配表示单词结尾的分隔符(>
)。尽管这个正则表达式并不能匹配所有的标签,但对于这个特定的例子来说,已经够用了。
Grep一词的来历
请仔细琢磨一下
:global
命令的简写形式:➾ :g/re/p
re
表示regular expression,而p
是[cmd]
使用。如果我们把符号 / 忽略掉,便会发现单词“grep”已然呼之欲出了。
用 ':v/re/d' 只保留匹配行
这一次,我们将进行相反的操作。正如我们前面提到的,:vglobal
或简写的 :v
命令恰好与 :g
命令的操作相反。也就是说,它用于在指定模式的非匹配行上执行Ex命令。
在本例中,包含URL的文本行很容易识别,它们都含有 href
属性。因此,运行以下命令,可以得到这些文本行。
➾ :v/href/d
以上命令可以解读为“删除所有不包含 href
的文本行”。最终的结果如下。
<a href="/episodes/show-invisibles/">
<a href="/episodes/tabs-and-spaces/">
<a href="/episodes/whitespace-preferences-and-filetypes/">
仅仅凭借一条命令,整篇文档就被精炼为我们感兴趣的文本段了。
技巧100 将TODO项收集至寄存器
通过把
:global
和:yank
这两条命令结合在一起,可以把所有匹配{pattern}
的文本行收集到某个寄存器中。
下列代码包含了几行以“TODO”开头的注释行。
global/markdown.js
Markdown.dialects.Gruber = {lists: function() {// TODO: Cache this regexp for certain depths.function regex_for_depth(depth) { /* implementation */ }},"`": function inlineCode( text ) {var m = text.match( /(`+)(([\s\S]*?)\1)/ );if ( m && m[2] )return [ m[1].length + m[2].length ];else {// TODO: No matching end code found - warn!return [ 1, "`" ];}}
}
假设想把所有TODO项收集到一起。只需输入以下命令,这些信息就会变得一览无余。
➾ :g/TODO
《 // TODO: Cache this regexp for certain depths.// TODO: No matching end code found - warn!
请牢记,:print
是 :global
命令的缺省 [cmd]
,它只是简单地回显所有匹配单词“TODO”的文本行。这并没什么用处,因为一旦执行了其他命令,这些信息将会消失。
这里介绍另外一种做法。先将所有包含单词“TODO”的文本行复制到某个寄存器,再把寄存器的内容粘贴到其他文件中,以备不时之需。
这一次,将用到寄存器a。首先运行 qaq
,将其清空。对这个命令进行分解。qa
会让vim开始录制宏,并把它存到寄存器a中,最后的 q
则负责终止录制。由于在录制宏的过程中,我们没有敲击任何按键,因此寄存器最终被清空了。可以用下面的命令印证一下。
➾ :reg a
《--- Registers ---"a
现在,可以把包含TODO注释的行复制到此寄存器中了。
➾ :g/TODO/yank A
➾ :reg a
《"a // TODO: Cache this regexp for certain depths.// TODO: No matching end code found - warn!
此处有一个窍门,即要用大写字母A引用寄存器。这意味着Vim将把内容附加到指定的寄存器,用小写字母 a
的话,则会覆盖原有寄存器的内容。因此,这条global命令可以被解读为“将所有匹配模式 /TODO/ 的文本行依次附加到寄存器 a
。”
这一次,当再次运行 :reg a
时,会发现寄存器 a
已经存有两组源自文档的TODO项了。(为了方便阅读,已将这些内容调整为两行,但在Vim中,换行符实际会显示为 ^J。)此后,只需在任意分割窗口中打开一个新缓冲区,再运行 "ap
命令,就可以将寄存器 a
的内容粘贴进去了。
结论
本例只收集了两个TODO项,即使手动操作也可以很快地完成。但是,以上介绍的技术具有很好的扩展性。如果某篇文档包含十几个TODO项,采用该技巧将使我们事半功倍。
甚至可以将 :global
命令与 :bufdo
或 :argdo
一起搭配使用,从一组文件中收集所有的TODO项。这个任务就留给你作为练习吧,可以参考技巧36中类似的工作流程。
还有另外一种方案:
➾ :g/TODO/t$
这里用到的 :t
命令已经在技巧29中介绍。该命令是将所有TODO项复制到当前文件的末尾,而不是把它们附加到寄存器。一旦运行完该命令,就可以在文件的末尾看到这些TODO项了。由于此法不会影响寄存器的内容,因此相对简单直接,但它在与 :argdo
以及:bufdo
命令一起使用时不太干净利落。
技巧101 将CSS文件中所有规则的属性按照字母排序
当Ex命令与
:global
一起组合使用时,也可以为[cmd]
单独指定范围。Vim允许以:g/{pattern}
为参考点,动态地设定范围。接下来,看看如何利用这一点,将CSS文件中每一条规则的所有属性均按照字母顺序排列。
用以下 CSS 文件作为演示。
global/unsorted.css
Line 1 html {- margin: 0;- padding: 0;- border: 0;5 font-size: 100%;- font: inherit;- vertical-align: baseline;- }- body {10 line-height: 1.5;- color: black;- background: white;- }
假设想把每一组规则内的属性都按照字母顺序排序。借助Vim的内置命令 :sort
(参见:h :sort
),就可以实现这一功能。
对单条规则的属性进行排序
先用 :sort
命令在该文件的子集上练练手(参见表15-1)。
首先,使用文本对象 vi{
,可以轻易地选中一段由 {} 所围的文本块。然后,运行 :'<,'>sort
,便可以将这些文本行按照字母顺序重新排列了。如果每次仅对一条规则进行排序,此法完全可以胜任,但假设我们遇到的是一个包含数百条规则的样式表呢?如果能把这一过程自动化岂不更好么?
表15-1 对文件的子集进行排序
按键操作 |
缓冲区内容 |
---|---|
{start} |
html { |
vi{ |
html { |
:'<,'>sort |
html { |
对所有规则的属性进行排序
其实,可以用一条 :global
命令对文件中所有规则的属性进行排序。假设在本例的样式表中运行以下命令。
➾ :g/{/ .+1,/}/-1 sort
最终会得到以下结果。
html {border: 0;font-size: 100%;font: inherit;margin: 0;padding: 0;vertical-align: baseline;
}
body {background: white;color: black;line-height: 1.5;
}
这条排序命令会在每条规则的{} 块内执行。尽管本例中的样式表仅仅包含十几行文本,但对于内容更多的CSS文件,此法也同样适用。
这条命令很复杂,但掌握其机理后,将会由衷地赞叹 :global
命令的强大。:global
命令的标准格式如下。
:g/{pattern}/[cmd]
请牢记,Ex命令通常都会接受“范围”作为其参数(正如技巧28讨论的那样)。对于:global
命令内部的 [cmd]
,该规则依然有效。因此,可以将命令的模板扩展成以下形式。
:g/{pattern}/[range][cmd]
实际上,可以用 :g/{pattern}
匹配作为参考点,动态设置 [cmd]
的 [range]
。. 符号通常表示光标所在行,但在 :global
命令的上下文中,它则表示 {pattern}
的匹配行。
可以把原有的命令拆分成两条单独的Ex命令进行讲解,先分析命令的后半部分。以下是一条有效的Ex命令。
➾ :.+1,/}/-1 sort
如果去掉范围中的偏移,该范围可简化为 .,/}/
,其含义是“从当前行开始,一直到匹配模式 /}/ 的那一行为止”。偏移值 +1 与 —1 仅仅用于缩小操作范围,让我们把目光集中在 {} 之间的内容上面。对于排序前的原始CSS文件,如果把光标置于第1行或第9行,以上这条Ex命令将会对相应 {} 之内的规则按照字母顺序重新排序。
也就是说,只需将光标置于每个{} 块的起始位置,再运行 :.,/}/ sort
命令,即可将其中的规则按照字母顺序重新排序了。明白了么?现在,试着用 :global
命令中的 {pattern}
执行一次查找。
➾ /{/
以上命令会将光标置于某个 {} 块的起始位置,即我们的目标所在。现在,再重新将 :global
与 Ex命令 [cmd]
组合在一起。
➾ :g/{/ .+1,/}/—1 sort
其中,模式 { 会匹配每个 {} 块的起始行。而对于每个匹配行,:sort
会在匹配行到 {} 块的结尾这个[range]
范围内执行。最终,每一条规则的CSS属性都会按照字母顺序排列整齐。
结论
:global
命令的广义形式如下。
:g/{start}/ .,{finish} [cmd]
可以将其解读为“对从 {start}
开始,到 {finish}
结束的所有文本行,执行指定的 [cmd]
”。
对于 :global
命令与任意Ex命令的组合,都可以采用相同的范式。例如,假设想对某一段指定范围内的文本内容进行缩进,用Ex命令 :>(参见:h >
)就可以实现。
➾ :g/{/ .+1,/}/—1 >
《 6 lines >ed 1 time3 lines >ed 1 time
注意:
与 :sort不同的是,每当调用 :> 命令时,Vim都会提示一条信息。如果在 [cmd] 的前面加上 :slient(参见
:h :sil
),就可以屏蔽这些信息:➾ :g/{/sil .+1,/}/−1 >
此法尤其适用于
:g/{pattern}
匹配大量文本行的情况。
本文摘自《Vim实用技巧》(第2版)
Vim是一款功能丰富而强大的文本编辑器,其代码补全、编译及错误跳转等方便编程的功能特别丰富,在程序员中得到非常广泛的使用。Vim能够大大提高程序员的工作效率。对于Vim高手来说,Vim能以与思考同步的速度编辑文本。同时,学习和熟练使用Vim又有一定的难度。
本书为那些想要提升自己的程序员编写,阅读本书是熟练掌握高超的Vim技巧的必由之路。全书共21章,包括123个技巧。每一章都是关于某一相关主题的技巧集合。每一个技巧都有针对性地解决一个或一类问题,帮助读者提升Vim的使用技能。本书示例丰富,讲解清晰,采用一种简单的标记方法,表示交互式的编辑效果,可以帮助读者快速掌握和精通Vim。
本书适合想要学习和掌握Vim工具的读者阅读,有一定Vim使用经验的程序员,也可以参考查阅以解决特定的问题。
Vim实用技巧:global命令相关推荐
- vim实用技巧(第二版)........持续更新ing
全书共123个技巧,每天更新两个,计划两个月更新完. (目前更新完技巧39) vim实用技巧第二版全部教学内容 前言 第1章 Vim解决问题的方式 技巧1 认识 . 命令 技巧2 不要自我重复 ...
- Vim实用技巧pdf
下载地址:网盘下载 内容简介 · · · · · · vim是一款功能丰富而强大的文本编辑器,其代码补全.编译及错误跳转等方便编程的功能特别丰富,在程序员中得到非常广泛的使用.vim能够大大提高程序 ...
- vim实用技巧-笔记(第九章)
vim实用技巧-笔记(第九章) 前言 我记得很早以前我就说过了,我是一个菜鸟,我写博客的主要目的不是为了别人,更多的是为了记录自己的成长过程.如果阁下认为我的行为是在划水的话,那我也不妨大方地承认. ...
- 《Vim实用技巧(第2版)》——1.4 执行、重复、回退
本节书摘来自异步社区<Vim实用技巧(第2版)>一书中的第1章,第1.4节,作者:[英]Drew Neil(尼尔)著,更多章节内容可以访问云栖社区"异步社区"公众号查看 ...
- Vim实用技巧_2.普通模式和插入模式
下面介绍vim的几种常用模式的技巧 vim有4种模式:普通模式,插入模式,可视模式,命令模式 为什么要分这么多模式? 想一想我们平时常用的编辑工具word,应该是将上面4种模式融合在一起的:这种做法的 ...
- 《Vim实用技巧(第2版)》学习笔记:技巧12-双剑合璧,天下无敌
<Vim实用技巧(第2版)>学习笔记:技巧12-双剑合璧,天下无敌 1. 操作符 + 动作命令 = 操作 d{motion}命令可以对一个字符.一个完整单词或一整个段落进行操作,它作用的范 ...
- 《Vim实用技巧(第2版)》——2.6 双剑合璧,天下无敌
本节书摘来自异步社区<Vim实用技巧(第2版)>一书中的第2章,第2.6节,作者:[英]Drew Neil(尼尔)著,更多章节内容可以访问云栖社区"异步社区"公众号查看 ...
- Vim实用技巧高清完整版PDF中文
Vim实用技巧高清完整版PDF是一本中文版的参考教材,该书适合想要学习和掌握 Vim 工具的读者阅读,有一定 Vim 使用经验的程序员,也可以参考查阅以解决特定的问题. 欢迎大家下载阅读学习:http ...
- Vim实用技巧(第2版)
ISBN:978-7-115-42786-1 作者:[英]Drew Neil 译者:杨源 车文隆 页数:289页 阅读时间:2020-04-05 推荐指数:★★★★★ Linux系统默认的经典强大的文 ...
最新文章
- 14PS中的切图基本操作
- 解决django配合nginx部署后admin样式丢失
- 神经网络的分类准确率是100%到底意味着什么?
- CSS中隐藏内容的3种方法及属性值
- 公共方法-利用for else搜索字典列表-for else
- wp自定义帖子没标签_拼多多搜索智能推广和自定义推广区别在哪里?
- 手机做服务器性能咋样,服务器性能不足 怎样才能逼出最强状态
- 前端发送http的get请求 - 代码篇
- linux mysql 8.0启动不了_MySQL官方源从8.0.3直接yum升级到8.0.4后无法启动
- 10个人做抖音,8个做不起来,为啥?
- PID算法原理及基本实现
- 论文《Efficient Large-Scale Stereo Matching》学习
- 科研论文画图技巧分享!超级实用!
- git提交代码时账号或密码错误
- oracle logged on,ORA-01012:not logged on的解决办法
- win10系统去除桌面图标小箭头
- 表示学习(Representation Learning)之局部表示(Local Representation)与分布式表示(Distributed Representation)
- Java面试题自我总结
- 信号完整性之S参数(六)
- 程序员返乡卖羊肉年销售1500万元,竟然是为了爱情?
热门文章
- 计算机网络基础(进制转换和IP地址详解)
- idea创建项目pom依赖爆红
- android设置ap密码,Android AP Wifi - 以编程方式更改网络共享密码(setWifiApConfiguration)...
- mysql procedure返回值_mysql procedure 返回结果集
- js在浏览器控制台输出
- upc 要塞任务 数论
- Android音频相关(四)设置铃声流程总结
- python爬虫经典段子_Python爬虫-抓取糗事百科段子
- 小米笔记本Pro 2020款 显卡MX350 CUDA+cuDNN tensorflow-gpu安装
- (Ver 0.5)油猴脚本:微信推送浏览功能拓展