当前位置: 首页 > 编程日记 > 正文

vim 成“神“之路 (一)

文章目录

  • 1. 安装
    • 1.1 linux
    • 1.2 MacOs的安装
    • 1.3 Windows的安装
    • 1.4 vim中文帮助文档安装
  • 2. vim基本概念和基础命令
    • 2.1 基本的键位映射如下:
    • 2.2 vim模式
    • 2.3 vim的选项和基本配置
      • 2.3.1 备份和跨会话撤销文件
      • 2.3.2 vim中支持鼠标
  • 3. vim 常用命令 -- 应对稍复杂任务
    • 3.1 光标移动
    • 3.2 文本修改
    • 3.3 文本对象选择
    • 3.4 文本移动 -- 更快
    • 3.5 重复操作
  • 4. vim 的简单定制
    • 4.1 vim 的目录结构
    • 4.2 vim 软件包
  • 5. vim 的复制与粘贴
  • 6. vim的模式匹配:正则表达式
    • 6.1 基本的特殊字符
    • 6.2 特殊模式项
    • 6.3 一些搜索举例
      • 6.3.1 最长匹配和最短匹配
      • 6.3.2 搜索加亮和取消
      • 6.3.3 正则表达式替换
      • 6.3.4 替换实例

哈哈,有点标题党的意思,vim带你成"神"?还是你通过vim成了"神"?还是学习了vim,感觉vim就是"神"? 仔细耐心体验一下vim的"神迹"。

vim 作为程序员三大美德体现:懒惰,急切,傲慢 的优秀编辑器,已经走过了接近三十个年头。

从肯·汤普逊 1978年将unix 操作系统传播开来,到比尔·乔伊 完成第一个版本的全屏编辑器 vi的开发(在此之前有很多基于行的编辑器ed,em,en ,ex),再到布莱姆·穆勒纳尔 持续维护了三十年的vi 克隆版本, 最后也就演变成了我们现在使用的vi IMproved – vim。

vim的优点如下:

  • vim 是一个完全跨平台的编辑器
    从开始的unix,到 现在最为通用流行的 linux,windows,Macos,再到不经常用的操作系统OS/2, BeOS,甚至ios和android也能找到vim的移植版本。
  • vim 是一个高度定制和可扩展的编辑器
    通过vim 自身脚本语言(Vim Script)可以扩展vim的功能,如果vim 脚本能力还不足,则可以通过Python ,Perl 等其他通用脚本语言进行扩展。这样就能够非常自由得打造属于自己的专属环境。
  • vim 良好的生态环境
    网络上已有的现成的脚本和插件,能够直接搭建顺手的开发环境。像经常用的语法补全,语法检查等常用功能,都可以在vim下实现,且能够通过配置 不需要离开vim 编辑器就能完成从写代码、到编译运行的大部分工作。

有这么多优点,又是无数大佬自己使用的编辑器,那么vim 就需要快速搞起来,来让自己的工作效率进一步提升,希望这篇成神之路能够带给你在vim上足够多的帮助。
客观来讲,vim的配置确实非常繁琐,甚至复杂,想要达到现在vscode ,clion的方便程度确实会花费不少时间。但vim的高效是能够在手指不离开键盘的情况下完成任何场景下的编辑工作,手指快速敲击三个键以内就能够达到一段文本的增删改查。

当然打造自己的vim 感觉 就像是公元前1500年前后 印欧语系游牧的蛮族潜心打造的青铜器,青铜战车 ,马具马鞍,戴着他们横扫了整个欧亚大陆的古代文明,从尼罗河的埃及文明到地中海的米诺斯文明,到幼发拉底河和底格里斯河的美索不达米亚文明,到印度河文明和中国的商朝(北方的游牧民族)都被精良高效的战争民族所取代,颠覆了整个大陆的格局。
vim所做的就是能够一统整个ide的大陆,用灵活的插件搭配强大的快捷操作实现 ,我们只需要在这个大陆上专注耕耘,建立自己的的伟大帝国。

先瞅瞅当前我的vim 使用上的一些效果:

  • 窗口分割
    在这里插入图片描述
  • 自动补全
    在这里插入图片描述
  • markdown
    在这里插入图片描述
  • 查看文件历史修改记录
    在这里插入图片描述
    这上面仅仅是展示很小很小一部分插件的编辑功能,每一种编辑功能都会有很多更加方便的细节配置。
    同时 本文也只是提供一条道路,希望大家能够在这条道路上找到适合自己的编辑模式。

最后vim 当然也能够支持阅读源代码,只不过源代码显示上不太舒适,这里使用clion这个老东家也很久了,所以还是不能喜新厌旧呀,用它作为撸源码的工具 还是很给力,而vim主要用在编辑或者写代码之上。

vimrc已经放置在vim-github,不过需要vim版本在8.2以上,或者neovim在0.4.4版本才行。
如果能够看懂vimrc中的简单vim script,建议先熟悉一下基本键位和操作,熟悉之后会发现编辑查看效率 急速飙升,指尖如飞。

1. 安装

1.1 linux

  • Redhat 和 Centos

    查看是否已经安装vim

    yum list installed |grep vim
    

    如果只有如下这样的输出,则说明是最小的vim安装

    vim-minimal.x86_64             2:7.4.160-2.el7          @centos7.3-x86_64-base
    

    建议使用sudo yum install vim-enhanced.x86_64安装增强版的vim。

  • Debian 和 Ubuntu
    使用apt进行安装,同时在这两种系统下vim有比较多的功能

    vim
    vim-athema #适用于老的 X-window 界面
    vim-gnome
    vim-gtk  #使用于GTK环境
    vim-gtk3 #适用于GTK环境
    vim-nox #有比较全面的文本界面vim包
    vim-tiny #最小功能的vim包
    

    安装可以遵循如下规则

    • 如果系统使用的是GNOME桌面环境时,安装vim-gtk3vim-gnome
    • 如果使用的是KDE桌面 ,安装vim-gtk
    • 如果使用文本界面,安装vim-nox

    可以通过apt list --installed|grep vim查看已经安装的vim版本

    安装:

    sudo apt update
    sudo apt install vim-gtk3
    

    手工编译安装,至少加上Python 支持和图形界面的支持:

    ./configure --enable-pythoninterp \--enable-python3inerp \--enable-gui=auto      #auto可以根据需要换成gtk3等其他数值
    make -j
    sudo make install
    

    安装成功之后,通过vim --version能够看到一个python版本的支持。
    在这里插入图片描述

1.2 MacOs的安装

直接使用homebrew进行安装
brew install vim
brew install macvim

参考homebrew进行mac下的homebrew的安装

1.3 Windows的安装

通过网址https://www.vim.org/download.php#pc下载windows版本的vim.exe,windows下的vim版本还是以32位为主,基本也满足正常的开发需求了。
安装过程中进入如下界面:
在这里插入图片描述
需要注意如下几个选项:

  • “安装批处理文件 (Create .bat files)” 对于使用Vim命令行的开发者来说是刚需,所以需要选择
  • “创建图标 (Create icons for vim)” 根据个人选择展开
  • “创建默认配置文件” 去掉这一项,可以通过后面会说到的方式创建配置文件
  • “安装多语言支持” 使得vim的菜单可以支持多语言选项

点击下一步,修改安装的文件目录,安装完成即可。
这个时候会打开一个默认的README文件,输入:e \_vimrc,输入如下内容:

set enc=utf-8
set nocompatiable
source $VIMRUNTIME/vimrc_example.vim

ZZ 退出即可

这里说一下windows和linux下vim的区别

  • windos下vim配置文件是_vimrc,unix下一般默认~/.vimrc
  • windos下打开的vim文件都成为了_ 开头,如_viminfo
  • 打.开头的vim配置目录.vim,也变成了vimfiles

同时windos下vim的插件安装也是比较费劲的,其实希望成为vim"之神"的同学应该以类unix环境为主,至少一个虚拟机下安装ubuntu镜像也并不会消耗太多的时间。

1.4 vim中文帮助文档安装

英文版的教程,使用 终端下直接输入 vimtutor 即可看到,同时一些网友也翻译了中文版本的vim帮助文档,这个安装在vim8中也是非常简单的。
以类unix环境为例(windows下需要将.vim 改为vimfiles目录),执行如下命令:

cd ~/.vim
mkdir -p pack/my/start/
git clone https://github.com/yianwillis/vimcdoc.git pack/my/start
cd pack/my/start
./vimdoc.sh -i #安装help.txt的中文帮助文档
./vimdoc.sh -u # 如果不想要中文版的help信息,则可以卸载掉

进入vim,输入:help 之后可以有如下的效果:
在这里插入图片描述

一般类unix操作系统,可以通过LANG=zh_CN.UTF-8 vimtutor 来进入一个中文版本的vim教程
在这里插入图片描述

PS:因为vim使用ctrl键会比较多,建议大家学习的时候将ctrl映射到之前的CAPS(mac下),或者windows CapsLock下

2. vim基本概念和基础命令

2.1 基本的键位映射如下:

在这里插入图片描述
建议大家在看完之前的vim 教程之后在来熟悉这一块,保证上面的基本命令都已经很熟悉了。
以上图没有说明vim的命令行命令

  • :q! – 不保存退出
  • :wq– 保存退出
  • :s – 替换
  • :! – 执行外部unix命令
  • :edit – 一般缩写为:e,编辑文件
  • :w – 写入指定文件
  • :r – 读文件
  • :help 查看帮助信息
  • 使用Ctrl + DTab键将命令补全

2.2 vim模式

  • 正常模式(普通模式):缺省的编辑模式,如果不加特殊说明,一般提到的特殊命令都直接在正常模式下输入;任何其他模式都可以通过键盘上输入ESC回到普通模式
  • 插入(insert) 模式:输入文本时使用,普通模式下键入i(insert)或则a(append)即可进入插入模式
  • 可视(visual)模式:用于选定文本块,可以使用v键来按字符选择,vim中也提供了按行和块进行选择的方法
  • 命令行(command-line)模式: 用于执行较长,较复杂的命令。普通模式键入: 即可进入该模式。 使用/或者?开始搜索也算作命令行模式。命令行模式下需要输入回车才算完成。

再次强调,只要按下ESC,无论在哪个模式下,都会回到普通模式。
这里再次说明以下,可以利用好vim命令行下的help帮助文档,能够提供非常方便的帮助操作。
在这里插入图片描述

2.3 vim的选项和基本配置

随着持续不断得使用vim,它的配置会不断得增加,从而应对自己在不同场景的需求。
接下来看看一些基本的vim配置,之前说过unix系统下的vim配置是.vimrc文件,windows的配置则是_vimrc文件

set enc=utf-8
set nocompatiable
source $VIMRUNTIME/vimrc_example.vim

如之前的一段类似于shell 脚本的 配置如上,三行的基本含义如下:

  • 设置编辑文件的编码格式为utf-8
  • 设置Vim和vi不兼容
  • 倒入vim的配置示例(示例中包括一些有用的选项:语法高亮,搜索高亮,命令历史等等)

2.3.1 备份和跨会话撤销文件

vim支持跨会话的编辑能力,这个在目前的编辑器中还没有其他的能够做到的。举个例子,编辑完word,将word关闭,再重新打开,想要做到撤销上一次的操作,或者恢复到之前n次操作,这个不可能的,vim能够支持这样的功能。

基本配置如下两个:

set backup
set undofile
  • 第一个选项使得我们的每一次编辑都能够保留上一次的备份文件
  • 第二个选项使得vim重新打开一个文件时仍然能够撤销之前的编辑(undo),还会保留一个编辑历史的文件(undofile)

这个时候当前目录下会出现针对编辑后文件的些~结尾的备份文件和.开头的undo文件
在这里插入图片描述
这里通常只保留撤销文件的功能,有了跨会话撤销的能力,基本备份的功能就用不到了,将撤销的文件放在个人用户目录下,保证文件的安全和目录的干净。

set nobackup
set undodir=~/.vim/undodirset undodir=~\vimfiles\undodir "windos下的形态,目录符合和unix有差异

为了保证目录存在,可以再增加如下判断:

if !isdirectory(&undodir)call mkdir(&undodir, 'p' , 0700) 
endif

&undodir是之前设置的undodir值,mkdir括号内部指定mkdir的命令选项 和 目录权限

2.3.2 vim中支持鼠标

我们正常使用vim的过程中,看代码肯定比写代码要多, 所以这个时候鼠标还是比较有必要存在的。而且鼠标在非线性跳转上比键盘快很多。

我们在vim中对鼠标的需求是:

  • vim内部使用鼠标通过可视模式(visual)选择内容,且仅在vim内部使用
  • 通过将vim内部的可视模式选择的文本和外部操作系统进行编辑交互(在vim内部鼠标选择后复制,粘贴到外部系统软件之中)

所以针对以上两种的使用需求,vim都需要能够支持:

if has('mouse')if has('gui_running') || (&term =~ 'xterm' && !has('mac'))set mouse=aelseset mouse=nviendif
endif

3. vim 常用命令 – 应对稍复杂任务

3.1 光标移动

  1. 基本移动 :上、下、左、右 – k,j,h,l; 缺陷是这四个键不能在插入模式下移动

  2. 跳转行首:0, 跳转行尾: $, 跳转到行首到第一个非空白字符: ^

  3. 一次移动超过一个字符: b/w, B/W
    以上含义分别是:words backward, words forward,用来向后或者向前跳转一个单词。大写跳转和小写跳转的唯一区别就是小写和编程语言的标识符类似,认为一个单词的组成是由字母,数字和下划线组成;而大写则认为非空格字符都是单词。

  4. 根据单个字符进行选择:f/t, F/T
    以上含义是:找到下一个紧接着输入的字符(如果输入f/t,F/T之前加上数字n,那就是下面第n个),比如找到当前行的第二个d字符,输入f2d即可。两者的区别是f会包含这个字符,t不包含这个字符。大写的F/T则是进行反方向的搜索。

    比如下面字符串*nc = (struct mg_connection *) data; ,光标在括号内的第一个字符s的位置,我想一次删除括号内所有内容,如果不用f/t的话需要仔细考虑w的匹配规则,最后使用c3w,而现在我们只需要使用ct)直接匹配)就可以。

  5. 文章内移动:() 分别是移动到上一句和下一句;{}分别是移动到上一段和下一段

  6. 开头和结尾跳转:ctrl - Homectrl - End 跳转到文件的开头和结尾;ggG 也是分别跳转到文件到开头和结尾。
    只不过G这里的区别是跳转到最后一行的第一个字符,不是最后一个字符

3.2 文本修改

Vim的基本教程中我们知道c(change),d(delete),i(insert)都能够对文本进行修改,vim的原则是常用的功能要尽可能按键少。因此很多常用的功能在vim中都会有不同的按键,而且大写键也会相应得重载相近但稍不同的含义(最后一个字符的包含与不包含这样的区别)。

  1. d 加动作进行删除: dd删除整行,D相当于d$删除到行尾
  2. c 加动作进行修改: cc修改整行,C相当于c$删除到行尾并进行插入
  3. s 相当于cl,向右删除一个字符并进入插入模式,S相当于cc,替换整行
  4. i 在当前字符前进入插入模式;I则相当于^i把光标移动到行首非空白字符,进入插入模式
  5. a 在当前光标所在字符后面进入插入模式,A相当于$a,把光标移动到末尾,然后进入插入模式
  6. o 在当前行下方插入一个新行,然后在新行进入插入模式;O在当前行上方插入一个新行,并进入插入模式
  7. r 替换光标下的字符; R进入替换模式,每次按键替换一个字符,直到按下ESC退出替换模式
  8. u 撤销最近的一个动作;U 撤销当前行的所有修改

这一些按键基本能够让大部分的编辑任务在一两个按键就能完成,不过需要长期练习,形成肌肉记忆 。

3.3 文本对象选择

这个功能非常适合程序中的逻辑块编辑,方便我们在一般模式下对程序代码或者文件进行随意自如的修改。
基础键的命令c,,d 是用来对文本内容进行修改,而像a,i,w 这样的能键能够附加到基础操作命令之后,对一段文本进行快速修改操作。

针对文本"coding boy = z_stand" 的修改利用如上键可以有如下组合策略。假设光标停在coding 的d上

  1. dw delete word, 删除ding,结果是"co boy = z_stand"
  2. diw delete inside word, 删除coding,结果是" boy = z_stand"
  3. daw delete a word,删除coding, 还有一个空格。 结果是"boy = z_stand"
  4. diW 删除"coding ,结果是boy = z_stand"
  5. daA 删除"coding 还有一个空格。结果是boy = z_stand"
  6. di" 删除coding boy = z_stand 结果是""
  7. da" 删除"coding boy = z_stand" ,字符串包括双引号被全部删除
    这个操作后面加"或者其他的字符,比如(,则会删除与其匹配的)内部所有的内容

以上介绍的是d操作,同样的基础键还可以用c进行,只不过d是执行完成删除操作之后vim还是一般模式,而c是执行了之后进入插入模式。
同时像如下的几个键也能够支持文本对象的选择,可以像dc一样搭配a,i,w,单引号,双引号,左右括号等

  • 搭配s(sentence)对句子进行操作 – 适合英文文本编辑
  • 搭配p(paragraph) 对段落进行操作 – 适合英文文本编辑,以及带空行的代码编辑
  • 搭配t(tag) 对HTML/XML 标签进行操作 – 适合HTML, XML等代码编辑
  • 搭配`和’,对shell或者python等脚本代码进行操作
  • 搭配[] 方括号,对括号里面的内容进行操作
  • 搭配{} 大括号,对括号内容进行操作 – 适合C/C++语言
  • 搭配<> 角括号 – 适合C++ 模版操作

再进一步,在ai之前能够增加数字,表示操作多少个文本对象,适合针对嵌套文本的操作
比如
在这里插入图片描述

3.4 文本移动 – 更快

  • <C-B> 向上翻页
  • <C-F> 向下翻页
  • <C-U> 向上翻半页
  • <C-D> 向下翻半页
  • 5G 跳转到第五行
  • 6l 跳转到第六列
  • HM, L 当前屏幕下,分别移动光标到屏幕顶部,中间,底部
  • <C-Y><C-E> 保持光标不动,滚动屏幕,ctrl-y向上,ctrl-e向下
  • zt 将光标所在行滚动到屏幕顶部,zz将光标所在行滚动到屏幕中部,zb将光标所在行滚动到屏幕底部

3.5 重复操作

  • ; 重复最近的字符查找 f或者t操作
  • , 重复最近的字符查找, 反方向
  • n 重复最近的字符串查找操作(/和? 查找模式)
  • N 重复最近的字符串查找操作(/和?)反方向查找
  • . 重复执行最近的修改操作

4. vim 的简单定制

通过对vim目录,配置文件,扩展包管理器的一些介绍来让大家能够初步配置自己的vim

4.1 vim 的目录结构

vim的工作环境是通过运行支持的vim插件来设定的,合理得定制自己的vim需要了解vim的目录构造,知道怎么快捷得找到这一些存放插件的位置。
在vim8.2版本下,不同平台安装vim的位置有差异:

  • unix 下面 /usr/share/vim/vim82
  • mac下的MacVim 运行时软件位置 /Applications/MacVim.app/Contents/Resources/vim/runtime
    能够看到很多子目录,如autoloadcolorsdoc

    最常用的是如下几个目录:
  • syntax vim 的语法加亮文件
  • doc vim 的帮助文件
  • colors vim 主题配色方案
  • plugin vim的插件文件

syntax目录 为例,MacVim支持619种语法高亮格式,.vim之前的内容就是支持的语言语法。
在一般模式下可以通过:setfiletype cpp来指定cpp文件的语法高亮。

同时一般模式下输入:help显示的帮助信息都在doc目录之下;通过:colorscheme 加tab键能够看到很多种不同的配色主题,这一些主题配色都会在color目录之下。
可以在.vimrc配置中加入一行 color desert ,指定每次启动vim加载的配色方案

接下来重点看一插件plugin目录,能够在原生vim下支持无数便捷的插件接入,这也是为什么vim被成为编辑器之神的原因。像我们在clion,vscode,sublime中体验到的便捷特性(代码补全,源码阅读时的跳转,代码调试等)都能够在vim中通过插件得到配置,而且我们能够将快捷键通过vim script的map减少来进一步加快编辑操作,以上是一些可以扩展的插件,而plugin目录下的插件则是系统内置的插件,分别具有如下功能:

  • getscriptPlugin.vim 获得最新的vim脚本插件
  • gzip.vim 编辑.gz结尾的压缩文件,打开时能够自动解压缩,保存为.gz结尾的文件时自动压缩
  • logiPat.vim 模式匹配的逻辑运算符,允许以非标准正则表达式来写模式匹配
  • manpager 使用vim来查看man帮助文档
  • matchparen.vim 对括号进行高亮匹配
  • netrwPlugin.vim 从网络上编辑文件和浏览目录(支持多种协议如ftp和scp,可以直接打开目录来选择文件)
  • rrhelper.vim 支持--remote-wait 编辑,vim的多服务器会用到这一个功能
  • spellfile.vim 在拼写文件缺失时自动下载,vim一般只安装了英文的拼写软件
  • tarPlugin.vim 支持编辑(压缩).tar结尾的压缩文件,这里和.gz不同的是不支持写入
  • tohtml.vim 把语法加亮的结果转成html
  • vimballPlugin.vim 创建和解压.vba文件
  • zipPlugin.vim.gz类似,支持读和写 .zip结尾的压缩文件

这几个简单的默认配置插件已经能够体现出了一部分vim的强大之处,简单演示部分插件功能如下:

4.2 vim 软件包

vim 的目录有点传统的unix格式,一个功能(插件plugin)会分散在多个不同的目录下

  • 插件的主题通常会在plugin目录下
  • 插件的帮助文档会在doc目录下
  • 有一些插件只对某一些文件类型有效,会有文件放在ftplugin目录下
  • 有一些插件会有自己的文件类型检测规则,会有文件放在ftdetect目录下
  • 有一些插件有特殊的语法加亮,会有文件放在sytax目录下

我再mac上是使用vim-plug作为自己的包管理器,其他的vandle或者minpac都是可以的。

  • 下载:

    curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
    https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
    
  • 使用 plug对插件进行管理
    安装上vim-plug之后就可以在vim的配置文件中增加自己想要的插件,mac下的vim配置在~/.vimrc,windows可以通过打开vim输入:e \_vimrc 打开自己的vim配置文件。

    插件的安装设置需要遵循如下语法,在plug#beginplug#end之间就是我们要安装的插件,具体的插件需要通过Plug + 插件名称来指定安装的插件:

    这里需要注意的是阔行内的内容是插件下载之后的存放目录,可以自己指定,也可以按照下文中的目录存放。

    call plug#begin('~/.vim/plugged') 
    Plug 'mzlogin/vim-markdown-toc', { 'for': ['gitignore', 'markdown', 'vim-plug'] }
    Plug 'vimwiki/vimwiki'
    Plug 'terryma/vim-multiple-cursors'
    Plug 'junegunn/goyo.vim' " distraction free writing mode
    call plug#end()
    

    然后再保存配置文件,在vim中输入:PlugInstall命令就可以直接安装对应的插件了

    当然,还可以直接对插件进行更新,或者清理不需要的插件,这一些命令可以通过:Plug按tab键自动补全。整个vim的插件管理就变得非常方便了。

5. vim 的复制与粘贴

对于命令行形式的vim,想要将外界复制的内容粘贴到 vim 的文本之中,需要有如下几步:

  • 使用 vim 打开一个文件,进入 vim 的一般模式下
  • 通过一般模式的 跳转命令,将光标移动到需要粘贴的行以及列处
  • 输入i或者a等插入命令进入vim的插入模式
  • 通过键盘<ctrl-c>,粘贴到当前位置
  • ESC回到一般模式,ZZ存盘退出

如果不退出vim的话则还需要通过如下两步

  • 打开vim进入一般模式,通过:e file打开一个文件;可以使用<C-D>查看有哪一些文件,通过tab选择文件并自动补全
  • 存盘则通过: :w

但是如果粘贴内容含有缩进,而vim又不够新的情况,还会出现缩进之间在“打架”的情况,导致整个复制缩进一直基于上一个缩进的基础上在缩进。这个情况是因为vim分不清用户是在输入,还是在粘贴,输入此时会和粘贴冲突,则会有智能缩进、制表符转换等功能。
这个可以通过 :set paste 命令来让vim知道当前文件执行的是粘贴的命令,从而不会被智能缩进和制表符转换的功能影响。

6. vim的模式匹配:正则表达式

6.1 基本的特殊字符

我们在vim的一般模式中经常需要用到模式匹配或者查找命令,通过/,?或者进入vim的命令模式: 进行匹配操作。
vim中的正则表达式和其他常用正则表达式是有一些区别的,这里先简单介绍一下vim中的一些正则表达式的基础,在一个搜索表达式里面有如下字符,., [],*, $,^, ~, \ 都是具有特殊含义的字符

  • . 可以匹配除换行符外的任何字符,如a.可以匹配 aa, ab
  • * 表示之前的匹配源可以重复0次到多次,比如aa*可以匹配a, aa, aaa等, a.*可以匹配a, ababc等,但是两者都不能匹配b
  • ^匹配一行等开头,如果出现在模式的开头的话;如果在模式的其他位置,则表示字符本身
  • $ 匹配一行的结尾,如果出现在模式的结尾的话;在其他位置则表示字符本身
  • ~ 匹配上一次替换的字符,如果上一次把abc替换为了ate,那么~就匹配ate
  • [...] 匹配方括号内任意一个字符;方括号内如果第一个字符是^,表示对结果取反;除开头之外的-表示范围:如[A-Za-z]表示任意一个拉丁字母,[^+-*/]表示除了 +,-,*,/ 之外的任意一个字符。
  • \ 的含义取决于下一个字符,在大部分情况下包括上面的这几个(., [,],*, $,^, ~, \ ) ,代表后面这个字符本身;在跟某一些字符时有特殊含义。

除此之外就是普通的字符,并没有特别的含义;需要注意的是如果想要将搜索字符/作为普通字符来使用,则需要\/ 这样,否则vim看到的/就会以为模式结束了,导致错误发生。

如果模式中使用"/"作为路径的分隔符,在替换命令中可以使用使用其他模式中没有的符号作为分隔符。比如想把路径/path/
全部替换为/paths/ ,建议不要用:%s/\/path\//\/paths\//g ,这种样子非常容易出错。而应该使用类似的写法:%s!/path/!/paths/!g,当然这个只能用于替换命令。如果想要使用/作为搜索命令的话就没有太好的办法了,只能使用\/这样的形态。

6.2 特殊模式项

通过\开始的特殊表达式很多,如果我们想要全部了解的话可以通过help pattern-overview来详细查看,这里仅仅列举几个基本的特殊模式项:
在这里插入图片描述

  • \? 表示之前的匹配重复零次 或一次: 如aa\? 可以匹配"a", “aa”, 但不能完整匹配"aaa"(可以匹配前两个字符,后两个或最后一个字符)
  • \+ 表示之前的匹配原重复一次或多次:如aa\+ 可以匹配"aa",“aaa”, 但不能匹配"a"或"b"
  • \{n,m} 表示之前的匹配原重复n到m遍之间。如:a\{3} 可以匹配3个"a":“aaa”; a\{,3} 表示最多匹配3个"a", 支持匹配"", “a”, “aa"和"aaa”;大括号内两个数字都省略时等价于*, 也就是之前的内容可以匹配0次或多次。
  • \(\) 扩起一个模式, 从而组成单个匹配原:如\(foo\)\? 可以表示单词foo出现零次或一次。
  • \& 是分支内多个临接的分隔符,类似于“与”操作,表示每一项都要匹配成功,然后去最后一项的返回结果:如.*foo.*\&.*bar.* 匹配同时出现foo和bar的完整行。
  • \| 是多个分支的分隔符,类似于“或”的匹配,表示任意一项匹配成功即可:如foo\|bar可匹配foobar两个单词之一。

还有13个特殊模式项:

  • \< 匹配单词的开头
  • \> 匹配单词的结尾
  • \s 匹配空白字符
  • \S 匹配非空白字符
  • \d匹配数字,相当于[0-9]
  • \D 匹配非数字,相当于[^0-9]
  • \x 匹配十六进制数字,相当于[0-9A-Fa-f]
  • \w 匹配单词字符,相当于[^0-9A-Za-z_]
  • W 匹配非单词字符
  • \h 单词首字符: [A-Za-z_]
  • \H 非单词首字符: [^A-Za-z_]
  • \a 英文字母字符: [A-Za-z]
  • \A 非英文字母字符: [^A-Za-z]
  • \l 小写字符: [a-z]
  • \L 非小写字符: [^a-z]
  • \u 大写字符: [A-Z]
  • \U 非大写字符 [^A-Z]
  • \_ 其中 x 可以是以上任意一个字符: 对应字符类加上换行

6.3 一些搜索举例

  1. 想要准确匹配一个函数名:/ \<function_name\>
    在这里插入图片描述
    或者将光标移动到想要匹配的关键字上面,按下*,vim就会自动提取光标下的关键字,并自动添加\<\>进行搜索。

  2. 如上代码片段,我想要搜索ReoportError或者void,那么就想到了上面特殊模式中断\|字符

    输入 /\<ReportError\>\|\<void\>即可
    在这里插入图片描述

6.3.1 最长匹配和最短匹配

这里有一个问题就是我们想要搜索的内容中有很多特殊字符,整个模式会变得极其复杂。
而像*,\?,\+\{}都属于最长匹配(贪婪匹配),即模式 既可以匹配一个较长的字符串,也可以匹配一个较短的字符串的时候结果会是那个比较长的字符串。

相应的也会有一个最短匹配,同时匹配较长和较短字符是会产生较短匹配。在vim里面,最短匹配只有一种形式,{-n,m},起意义和之前说得{n,m}相同( \{n,m} 表示之前的匹配原重复n到m遍之间),但结果是较短而非较长的字符串。

以HTML 标签匹配为例,使用最短匹配的话,可以把模式写成/<.\{-1,}>,表示要求模式匹配的结果在一对尖括号里面且至少有一个字符,但越短越好。
在这里插入图片描述

6.3.2 搜索加亮和取消

如果也有在做上面但实验,会发现vim在搜索的过程中默认会将模式匹配的内容高亮,这个对确认自己的搜索结果是否正确非常重要。

但是如果你是用了非原生vim,比如某一个IDE的插件,那么就会发现并不是默认高亮。
而有的时候又觉得高亮太刺眼,想要去掉,这个时候vim就提供了比较方便的指令:nohlsearch或者:nohls
想要恢复高亮,则可以:set hlsearch或者:set hls

如果这两个取消和恢复高亮的指令使用非常频繁,则可以设置map键
noremap <LEADER><CR> :nohlsearch<CR> 我这里设置的是直接按LEADER键,我的LEADER键设置的是let mapleader=" "空格

6.3.3 正则表达式替换

替换我们正常理解就是利用之前提到的一些模式匹配特殊字符来完成,将一个字符串替换为另一个字符串。但是很多替换场景还是非常复杂的。

  • 可能要保留匹配中的某一些字符,而替换另外一些字符
  • 要对匹配出来的内容做大小写转换
  • 可能需要 “计算” 出替换结果
  • 可能要决定一行里面替换单次还是多次,是自动替换还是要 – 确认 ,等等。

接下来看看具体的操作

  1. 在替换结果中保留匹配出的字符
    之前我们说到\(\)特殊模式 除了将一个模式转变成匹配原之外,还有一个捕捉匹配的内容的作用。
    按照\(的出现顺序依次编号为1到9,并可以在模式和替换字符串中用\1\9 来访问。如果要在替换字符串中完整使用匹配内容的话,则可以使用\0&(字符 “&” 也因此要在替换字符串中写成\&)

    如果我想要找出作为函数调用的WebSocket ,那我可以写成\<WebSocket( ,虽然 (不是想要匹配的内容,但它是函数名称的一部分。从替换的角度来看需要多处理一下这个字符;在非匹配的内容比较复杂或者变化的时候,这个过程尤为麻烦。
    所以vim 里还有专门匹配开始和结束的匹配原,分别是\zs\ze

    对于上面函数调用的这个例子,搜索模式就应该是\<WebSocket\ze(,当然这个模式也可以匹配为\<WebSocket(\&WebSocket或者\<WebSocket(\&...

  2. 大小写转换的特殊替换字符串
    \U 把下面的字符串转变成大写,直到\E出现
    \u 把下一个字符变成大写
    \L 把下面的字符变成小写,直到\E出现
    \l 把下一个字符变成小写
    \E 结束大小写转换
    \= 开始一个返回字符串的表达式,用来计算出一个替换的结果

    和其他的编程语言一样,vim的正则表达式中支持\t\r\n等特殊转义字符,但在替换表达式中,\n插入的是空字符(NULL\0),而非在模式中正常的行尾符LF。如果想要插入行尾符的话我们需要使用\r。这意味着把一个回车变成两个,需要通过:s/\n/\r\r/ 这样尴尬的方式来实现。
    如果我们要插入CR(回车)的话,需要输入\<C-V><CR>才行。

6.3.4 替换实例

  • 删除行尾注释
    :%s!\s*//.*$!!
    把零到多个空白字符后面出现的"//" 直到行尾全部删除, ! 这个表示分隔符,是为了简化模式,否则就需要通过\/来不断转义

  • 删除/**/ 注释
    这个实现就非常复杂了,首先匹配内容可以跨行;其次,有跟HTML标签类似的问题(注释内部可能有多个/**/ ),需要使用最短匹配。
    通过如下来实现
    :%s!/\*\_.\{-}\*/!!g

    因为一行中可能有多个/**/,结尾通过g表示允许一行内部持续多次替换。

后续会持续分享vim的更高级操作,包括键盘宏,vim的插件,以及如何编写vim script来让自己的指尖 有效得 飞得更快。

相关文章:

android 添加头参数,Retrofit添加header参数的几种方法

(1)使用注解的方式添加一个Header参数publicinterfaceUserService {Headers("Cache-Control: max-age640000")GET("/tasks")Call> getTasks();}添加多个Header参数publicinterfaceUserService {Headers({"Accept: application/vnd.yourapi.v1.full…

redis下载地址

http://www.newasp.net/soft/67186.html转载于:https://www.cnblogs.com/phpxuetang/p/4190999.html

Ubuntu 13.10 安装软件失败后出现的问题——已安装 post-installation 脚本 返回了错误号 1...

安装Oracle-java7-installer失败后&#xff0c;再次重新安装后出现错误&#xff5e;&#xff5e; dpkg: error processing oracle-java7-installer (--configure): 子进程 已安装 post-installation 脚本 返回了错误号 1 索性执行 sudo apt-get install -f&#xff0c;我勒个…

C. Edgy Trees Codeforces Round #548 (Div. 2) 【连通块】

一、题面 here 二、分析 这题刚开始没读懂题意&#xff0c;后来明白了&#xff0c;原来就是一个数连通块里点数的问题。首先在建图的时候&#xff0c;只考虑红色路径上的点。为什么呢&#xff0c;因为为了不走红色的快&#xff0c;那么我们可以反着想只走红色的路径&#xff0c…

设计模式 之美 -- 策略模式

策略模式作为行为型设计模式中的一种&#xff0c;主要封装相同功能的不同实现算法&#xff0c;用于在用户程序内部灵活切换。对用户来说能够快速替换对应的算法&#xff0c;能够让算法的实现独立于使用的用户。 基本的UML类图如下&#xff1a; 用户使用Stratey的实例能够快速…

Good Bye 2014 B. New Year Permutation(floyd )

题目链接 题意:给n个数&#xff0c;要求这n个数字小的尽量放到前面&#xff0c;求一个最小的。 给一个矩阵s[i][j]1&#xff0c;表示位置 i 的数字可以和 位置 j 的数字交换。 分析&#xff1a; 刚开始用的是3个循环&#xff0c;每次都找一个能直接连接的最小的放到前面&#x…

android数据库查找一个字符,Android - 如何在Firebase数据库中对字符串进行简单搜索?_android_开发99编程知识库...

这个问题可能很旧&#xff0c;但是&#xff0c;有一种文档化方式&#xff0c;如何实现这种方式&#xff0c;很简单&#xff0c;引用 &#xff1a;要启用云Firestore数据的全文搜索&#xff0c;请使用第三方搜索服务(如Algolia &#xff0c;考虑一个笔记记录应用程序&#xff0c…

料酒有什么用?

http://zhidao.baidu.com/question/201086759.html?frala&devicemobile&ssid0&from844b&uid0&pusz%401320_1001%2Cta%40iphone_2_4.1_3_537%2Cusm%400&bd_page_type1&baiduidDFA2DBA38D5C3AEB12431C4258DC1F40&tjzhidao_1_0_10_title

jmeter对自身性能的优化

测试环境 apache-jmeter-2.13 1. 问题描述 单台机器的下JMeter启动较大线程数时可能会出现运行报错的情况&#xff0c;或者在运行一段时间后&#xff0c;JMeter每秒生成的请求数会逐步下降&#xff0c;直到为0&#xff0c;即JMeter运行变得很“卡”。 2. 解决方法 1&#x…

站在历史的长河中做农活

苹果的生长周期 国庆节回老家呆了3天时间&#xff0c;陪爸爸妈妈吃喝吃睡&#xff0c;除此之外就是帮爸爸妈妈去家里的果园做一些农活。 我们老家的 苹果种植是家庭主要的收入&#xff0c;每一家人或多或少都有一些果园。从春的剪枝&#xff08;高中生物中的降低顶端优势&…

html 基本用法

html表单表格基本用法&#xff0c;直接贴代码。 [html] view plaincopy<html> <head> <title>html基础</title> </head> </body> <center><h2><font color"CYAN">html基础&…

ecliplse 调试android 断点,如何在Github maven项目上开始调试

您将需要在 nifi-registry.sh 脚本中编辑此行以启用远程调试run_nifi_registry_cmd"${JAVA} -cp ${BOOTSTRAP_CLASSPATH} -Xms12m -Xmx24m ${BOOTSTRAP_DIR_PARAMS} org.apache.nifi.registry.bootstrap.RunNiFiRegistry $"它只是我&#xff0c;还是记忆足迹真的很小…

Linux认证体系

就像网络工程师的认证有思科系统和华为系列一样&#xff0c;Linux认证方面&#xff0c;不同的机构也有不同的证书&#xff0c;比如国内有红旗Linux的认证RCE&#xff08;红旗Linux认证工程师&#xff09;&#xff0c;国际方面有红帽的认证RHCSA&#xff08;Redhat认证的Linux系…

python2.7 Cheetah You don't have the C version of NameMapper installed

python2.7 Cheetah You dont have the C version of NameMapper installed 问题&#xff1a;You dont have the C version of NameMapper installed sudo vi /usr/lib/python2.7/site-packages/Cheetah/Compiler.py 将第1506行起以下代码注释掉&#xff1a; if not NameMapper.…

C++ 从双重检查锁定问题 到 内存屏障的一些思考

文章目录1. 问题描述2. DCLP 的问题 和 指令执行顺序2.1 Volatile 关键字2.2 C11 的内存模型3. C11内存模型 解决DCLP问题3.1 内存屏障和获得、释放语义3.2 atomic 的完整介绍3.2.1 原子操作的三种类型3.2.2 atomic 内存序3.2.3 atomic 成员函数4. 总结1. 问题描述 单例模式 是…

android系统的iphone,iPhone上安装Android系统详细步骤。

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼在iphone安装android系统的详细步骤首先&#xff0c;准备好iphone的多点触屏和wlan固件。因为法律的缘故&#xff0c;我们不能分享这些文件&#xff0c;你可以去ipsw文件里提取或去marvell网站下载。1、在linux的home目录下创建一个…

Linux下GCC和Makefile实例(从GCC的编译到Makefile的引入) 转

http://www.crazyant.net/2011/10/29/linux%E4%B8%8Bgcc%E5%92%8Cmakefile%E5%AE%9E%E4%BE%8B%EF%BC%88%E4%BB%8Egcc%E7%9A%84%E7%BC%96%E8%AF%91%E5%88%B0makefile%E7%9A%84%E5%BC%95%E5%85%A5%EF%BC%89/ 很给力的说&#xff0c;回头去搞搞&#xff01;

服务端如何识别是selenium在访问以及解决方案参考二

有不少朋友在开发爬虫的过程中喜欢使用Selenium Chromedriver&#xff0c;以为这样就能做到不被网站的反爬虫机制发现。 先不说淘宝这种基于用户行为的反爬虫策略&#xff0c;仅仅是一个普通的小网站&#xff0c;使用一行Javascript代码&#xff0c;就能轻轻松松识别你是否使用…

LSM 优化系列(二)-- dCompaction: Speeding up Compaction of the LSM-Tree via Delayed Compaction

文章目录背景描述dCompaction设计触发条件 VCT触发VT 合并的条件 VSMT测试数据优化的重心集中在减少写放大上&#xff0c;同时将读性能维持在和rocksdb 原生读性能接近&#xff0c;优化思想是中国科学院的2位博士 提出的。论文原地址&#xff1a;dCompaction: Speeding up Comp…

Android应用系列:完美运行GIF格式的ImageView(附源码)

前言 我们都知道ImageView是不能完美加载Gif格式的图片&#xff0c;如果我们在ImageView中src指定的资源是gif格式的话&#xff0c;我们将会惊喜的发觉画面永远停留在第一帧&#xff0c;也就是不会有动画效果。当然&#xff0c;经过略加改造&#xff0c;我们是可以让gif在Image…

wordpress怎么修改html,WordPress后台编辑器HTML模式界面中添加修改删除按钮

在WordPress编辑器HTML模式界面中添加按钮一文中&#xff0c;我大致介绍了怎么在后台添加一些自定义的按钮&#xff0c;本文则更为详细全面的对wordpress后台编辑器HTML模式下的按钮自定义进行详解&#xff0c;以让开发者肆意的修改按钮及其布局。自定义按钮起效的两种途径 ↑首…

OCA读书笔记(9) - 管理数据同步

9.Managing Data Concurrency 描述锁机制以及oracle如何管理数据一致性监控和解决锁冲突 管理数据的并发--管理锁数据的不一致&#xff1a;脏读更改丢失幻影读 脏读:数据是指事务T2修改某一数据&#xff0c;并将其写回磁盘&#xff0c;事务T1读取同一数据后&#xff0c;T2由于某…

Java EE学习笔记(四)

Spring的数据库开发 1、Spring JDBC 1)、Spring JDBC模块的作用&#xff1a;Spring的JDBC模块负责数据库资源管理和错误处理&#xff0c;大大简化了开发人员对数据库的操作&#xff0c;使得开发人员可以从繁琐的数据库操作中解脱出来&#xff0c;从而将更多的精力投入到编写业务…

SpringBoot 中实现订单30分钟自动取消的策略

在电商和其他涉及到在线支付的应用中,通常需要实现一个功能:如果用户在生成订单后的一定时间内未完成支付,系统将自动取消该订单。本文将详细介绍基于Spring Boot框架实现订单30分钟内未支付自动取消的几种方案,并提供实例代码。

一键部署 SpringCloud 微服务,这套流程值得学习一波儿!

一键部署 springcloud 微服务,需要用到 Jenkins K8S Docker等工具。本文使用jenkins部署,流程如下图开发者将代码push到git运维人员通过jenkins部署,自动到git上pull代码通过maven构建代码将maven构建后的jar打包成docker镜像 并 push docker镜像到docker registry通过k8s发起 发布/更新 服务 操作其中 2~5步骤都会在jenkins中进行操作。

Rocksdb 的 rate_limiter实现 -- compaction限速

文章目录前言1. Compaction为什么会影响Client qps1.1 基本LSM介绍1.2 LSM internal ops1.3 长尾延时的原因2. Rate limiter 基本限速接口3. Rate Limiter 限速原理实现3.1 Rate Limiter的传入3.2 Rate Limiter 控制 sync datablock的速率3.3 Rate Limiter控制写入速率4. rocks…

Oracle --获取绑定变量的值.

SELECT * FROM DBA_HIST_SQLBIND WHERE SNAP_ID>67073 AND SNAP_ID<67079 AND SQL_ID3DR3410F086P4;SELECT * FROM v$sql_bind_capture where sql_id http://blog.itpub.net/22034023/viewspace-689802/ 通过v$sql_bind_capture视图&#xff0c;可以查看绑定变量&#xf…

计算机网络TCP/IP协议-从双绞线到TCP

消息响应也是同理,这种带端口的消息发送方式,其实就是UDP协议,UDP简单粗暴,但是UDP存在很多问题,所以我们需要设计一个稳定可靠的协议,TCP协议,首先,网络是不稳定的,我们发送的消息很有可能会在中途丢失,所以需要设置重试机制,当消息发送失败时重新发送,为了判断是否成功,还需要要求接收方收到消息后,必须发送确认消息,这样就可以保证消息必达,另外大段的内容发送,很容易造成部分丢失,导致全部内容都要重新发送,于是我们可以将数据分包,分成多个包发送。到这,也行你会发现了,演示中的IP地址是怎么设置的呢?

使用HTML CSS完成初步的页面,任务九:使用HTML/CSS实现一个复杂页面(示例代码)

任务目的通过实现一个较为复杂的页面&#xff0c;加深对于HTML&#xff0c;CSS的实战能力实践代码的复用、优化任务描述整个页面内容宽度固定&#xff0c;但头部的蓝色导航和浏览器宽度保持一致任务注意事项只需要完成HTML&#xff0c;CSS代码编写&#xff0c;不需要写JavaScri…

Yii-yiic使用

原文在&#xff1a;http://blog.sina.com.cn/s/blog_862b12fb0101n00v.htmlyii提供了强大的命令行工具来快速的创建相关组件和应用。下面就来讲解用yiic工具快速创建yii应用我的web目录在d:\ EasyPHP-DevServer\data\localweb下&#xff1b;yiiframework在D:\EasyPHP-DevServer…