VIM 技巧

VIM 差不多半年了,最初发现VIM有很多的技巧,于是觉得有用的就记下来。
后来才渐渐发现这变成了一项多么浩大的工程,再不整理一下就堆成山了。
今天抽空收拾了一下,把用熟了的,没什么用的,重复的统统删了,
分类梳理了一下,缩减了不少,最终大概400多行,还好 !^_^

今天整理的比较粗略,有不少内容不全,分类也有些乱,
今后会慢慢补充修改的,希望这一页最后能由长变短。

文中有些内容来自于其他人的文章,因为出处太杂,而且无法追溯到原作者,
所以就不再特地注明出处了,请见谅.

查找文件编辑

:set path+=path_to_search "参考 :h 'path'
:find path_name_to_edit "可以是文件或目录!

shell 交互

直接运行shell

:sh(ell) 执行shell选项所指定的外部shell程序。退出后返回vim

直接运行命令

:!<cmd> 执行<cmd>命令,退出后返回vim

通过read write命令与shell交互

write

[用法] :[range]w !<cmd>
将[range]内的内容作为标准输入传给<cmd>命令执行.
注意w后的空格是必须的,w !sh 是写入给<cmd>命令作为输入
而w!<cmd> 是写入名为<cmd>的文件!
[示例] :write !sh

read

[用法]

  1. :r!<cmd> 读取ls的输出(插入内容), read 后可加空格
  2. :%!<cmd> 读取命令输出 (替换全文内容)
  3. :.!<cmd> 读取命令输出 (替换当前行内容)
  4. !!<cmd> 读取命令输出 (替换当前行内容)

第4种是直接在normal模式下执行的, 不需要切换至命令模式
其实你输入了!!后,vim就自动转换到 :.! 等待你继续输入

复杂些的例子

多个文件重命名, 把*.c更名为*.cpp。

:r !ls *.c
:%s/\(.*\).c/mv & \1.cpp
:w !sh

命令输出的重定向

参考 :h :redi[r] 重定向命令输出, 包括内部命令!
可以将目标设置成文件或buffer.
然后在运行命令之后, 结果会在VIM中输出的同时导入到你设定的目标.
其行为类似于tee, 或者就是用tee实现的.

替换 s[ubstitute]

默认不指定范围的行为是替换当前行,用%才能替换整个文件

选项

g - global
c - confirm
i - ignore case
e - don't show error?

常用

特殊变量

\<n> 匹配的第<n>部分,()用来表明需要匹配的子域
:%s/^(.*)\n\1/\1$/ : 删除重复行

& 匹配的全部
&替代整个匹配字串
:3,7s/.*/ &/ : 將3至7行向右移2個空白

特殊语法

\{- 非贪婪匹配,non-greedy matching

【用法】参考 :h /\{-
\{n,m} 匹配 n 至 m 个前面的匹配原。尽可能多
\{n} 匹配 n 个前面的匹配原
\{n,} 匹配至少 n 个前面的匹配原。尽可能多
\{,m} 匹配 0 至 m 个前面的匹配原。尽可能多
\{} 匹配 0 个以上前面的匹配原。尽可能多 (和 * 等价)

\{-n,m} 匹配 n 至 m 个前面的匹配原。尽可能少
\{-n} 匹配 n 个前面的匹配原
\{-n,} 匹配至少 n 个前面的匹配原。尽可能少
\{-,m} 匹配 0 至 m 个前面的匹配原。尽可能少
\{-} 匹配 0 个以上前面的匹配原。尽可能少

【示例】
:%s/^.{-}pdf/new.pdf/ 只是删除第一个pdf

/\_ 跨越可能的多行

:%s/<!--\_.\{-}-->// : 删除多行注释

printf 控制替换内容

如有一文件,内容为:
aa
bb
cc
dd
用:%s/.*/printf("& is :%d",&)/

插入任意内容

:s/date/\=strftime("%c")/ : insert datestring

特殊命令

:%s/\<Edward\>/\U&/g
將全文的 Edward 這個單字,改成大寫的

global 命令

可实现的功能很强大,待扩充

用法

:[range]g/pattern/[cmd]
range 不指定的話,默认是全文,
这与s默认是单行的行为有差别!而且:s 只更改一行里的內容,但无法作出刪除一行的动作
另外,有些变体命令
:g! 不匹配
:v 不匹配

示例

g/INFO/y A 可以把全文中有INFO的行grep出来追加到A寄存器中

命令行

选项

-tag 例如: vim [options] -t {tag} 编辑于标签 {tag} 关联的文件
-n No swap file, use memory only
-i <viminfo> Use <viminfo> instead of .viminfo
—noplugin Don't load plugin scripts
-p[N] Open N tab pages (default: one for each file)
-c 执行命令
例如 对一个文件执行多个命令
vim -c "%s/ABC/DEF/ge | update" file1.c

示例

1. 不要加载.vimrc和任何plugins (激活一个干净的VIM)

gvim -u NONE -U NONE --noplugin

2. 编辑当前目录下所有包含$1的文件并且跳转至$1
gvim.exe -c "/$1" $(grep -isl "$1" *) &

管道

<cmd> | vim - 将cmd命令的标准输出放入buffer中编辑
链接到%!<cmd>方式

命令行界面

Shift组合键 不起作用
左右Alt似乎有区别?

窗口管理

尺寸设置

这里有很多命令,需扩充…
z<N><CR> set window height

窗口位置控制

C-W J/K/H/L 将窗口移至边界
C-W T 将窗口移至新的tab中
C-W C-x 窗口交换

边界位置打开窗口

命令 to[pleft] bo[tright]
new 最顶端K 最底端J
vnew 最左端H 最右端L

预览

不怎么用,需要深入看看是否有用
??? :pt[ag] {tag} 打开一个显示 {tag} 标签的预览窗口
|:pclose| :pc[lose] 关闭标签预览窗口
|CTRL-W_z| CTRL-W z 关闭标签预览窗口

编程功能

内容很多而且比较独立于日常使用,所以另开一贴

寄存器

需要深入解释

"
无名寄存器

y操作的结果都放在"寄存器中, 如果选项 'clipboard' 含有 unnamed, 则也会写入剪贴板寄存器

常用操作

@q
用于执行q reg / 粘贴 reg content
@@
to Repeat
i_<C-R>q
用于输出reg
n_"qp
paste q reg
i_<C-R>
=== n_"

追加内容

“[a-z] 暫存器來使用的時候,事實上是把指定的內容覆蓋上去
附加而不是覆蓋呢?那就得使用 “[A-Z] 了
:g/pattern/y A
:g/pattern/. w » filename

剪贴板寄存器

@* 是选择区
@+ 是剪贴板, 用于copy, paste操作
VIM 退出或挂起时,@*会写入剪贴板
WIN上没有选择区功能

相关的选项有2个

set guioption+=a " in gui mode
set clipboard+=autoselect "in term mode
set clipboard+=unnamed "yank register also write clipboard "*

record macros

reg 和 record macros 都是存在regs里面的

编辑

:ce(nter) 本行文字置中。注意是冒号命令!
:ri(ght) 本行文字靠右。
:le(ft) 本行文字靠
所谓置中、靠左右,是参考 textwidth(tw) 的设定。
如果 tw 没有设定,预设是 80,就是以 80 个字元为总宽度为标准
来置放。

受shiftwidth(sw)控制,和tabstop无关!
>> 整行向右移一个 shiftwidth(预设是 8 个字元,可重设)。
<< 整行向左移一个 shiftwidth(预设是 8 个字元,可重设)。

<n>| 移至第 n 列, 注意,要用 Shift 键。n 是从1起算的。
:n 移至第 n 行行首。或 nG。

H 移至萤幕顶第一个非空白字元。
M 移至萤幕中间第一个非空白字元。
L 移至萤幕底第一个非空白字元。

To undo all the changes on a line, type: U (capital U) before you leave the line!
Shift+u is viewed as new modification on this line and can be undo by 'u'

s insert one char and return
r replace ……………..
Replace : r -> R -> c
c number motion
d number motion

D delete to end of line!
C change to ……..

重复上下行内容

单字母重复很慢,有没有办法可以连续重复多个,之前加count?
CTRL-E 插入光标下面的字符
CTRL-Y 插入光标上面的字符

tab

tapstop : Ctrl-v Tab 或 Ctrl-v I (可用 Ctrl_Q)
softtap : 按tap插入blank

indent控制

i_0_Ctrl-D 去除当前行所有indent
i_Ctrl-D indent 减少(«)
i_Ctrl-T indent 增加(»)

CTRL-A,CTRL-X : increment,decerement number under cursor

文本选择

a / i 修饰

外部选择 ( a<a> )
##< … >##
内部选择 ( i<i> )
<##…##>
其他 {, [雷同!

Visual模式

分类有些模糊,需要重新放置,并增加bookmark类
gv 启动可视模式,重新选择上一次的选择区和相同模式。
o 或 O 在选择的开始和结束位置间跳转
'< 标签存储了上次选择的开始行
'> 标签存储了上次选择的结束行

fold

需要添加内容
!!! syntax fold
set foldmethod=syntax

常用命令及函数

有些需要细分到其他类别去

多文件,多窗口操作

  1. Operate command over multiple files

:argdo %s/foo/bar/
:bufdo %s/foo/bar/
:windo %s/foo/bar/

命令历史窗口

q/ : Search history Window (puts you in full edit mode)
q: : commandline history Window (puts you in full edit mode)
:<C-F> : history Window

fnamemodify

修改文件名,类似expand的功能,但不限于%,#等,可以用于普通变量

map

nore… 可以禁止重复map或者abbr

option

:option

:opt[ion] 來直接線上設定,會列出目前的設定
改好後
:mk[exrc] 則會寫入 ~/.exrc 檔
:mkv[imrc] 則會寫入 ~/.vimrc 檔

:set 後面是可以多重設定的。例如 :set autoindent noconfirm autowrite,

:set 或 :se 會顯示所有經過修改的部份,就是和預設值不一樣的部份。
:set all 顯示目前所有設定值內容。
:set option? 顯示 option 這設定的目前值。

特殊字符

set list/nolist
:set list
:set nolist
list mode。就是 Tab 的地方會以 ^I 顯示,
而行尾之 EOL 會顯示成 $

set wrap/nowrap

com

set com for every syntax!
'comments' 'com' 字符串 (缺省 "s1:/*,mb:*,ex:*/,://,b:#,:%,:XCOMM,n:>,fb:-")
局部于缓冲区
{仅当编译时加入 |+comments| 特性才有效}
逗号分隔的可以开始注释行的字符串列表。见 |format-comments|。
|option-backslash| 说明如何包含空格和使用反斜杠。

swapfile

setlocal noswapfile

keywordprg ##brown#特色功能##

K在win为help, 在unix中为man? set keywordprg=:help
大寫 K 會顯示游標所在處之 word 的 manpage

:e!
return to unmodified file
:sort
sort embedded in VIM(use :sort)

c_<C-R><C-W> : Pull <cword> onto search/command line
cd %:h
lcd %:h (only for current window)
:f 或 Ctrl-g
显示目前编辑的档名、是否经过修改及目前游标所在之位置。
:P

特殊操作

:!! 執行前一次執行之外部指令。
vim 中有一個很特殊的指令 @:,是重複前一次的冒號命令
. repeat last command
只要是编辑动作(移动游标不算,冒号命令也不算)

g(GREAT) 打头的命令

n_guu : lowercase line
n_gUU : uppercase line
n_gf : open file name under cursor (SUPER)
n_ga : display hex,ascii value of character under cursor
v_g? : rot13 whole file

书签

需要深入

'.
jump to last modification line (SUPER)
.
jump to exact spot in last modification line

VIM 变量

$VIMRUNTIME 就是 $VIM/vimxx,xx 就是版本號碼啦!

退出

:wq 存档后离开。纵使档案未曾修改也是会再存一次档。
:x 也是存档后离开,但如果档案没有修改,则不会做存档的动作。
ZZ 和 :x 完全一样,随您高兴用哪一个。

跳转控制

文件跳转

CTRL-W gf 打开新标签页,并编辑光标下的文件名
CTRL-W gF 打开新标签页,编辑光标下的文件名,并跳转到文件名之后的行号上。
path 选项设定了搜索目录

|:ju| :ju[mps] 列出跳转列表
|:marks| :marks 列出活动的标记

|[#| N [# 向后至第 N 个未结束的 "#if" 或 "#else"
|]#| N ]# 向前至第 N 个未结束的 "#else" or "#endif"

|[star| N [* 向后至第 N 各注释的开始 "/*"
|]star| N ]* 向前至第 N 各注释的结束 "*/"

|[(| N [( 向后至第 N 个未结束的 '('
|[{| N [{ 向后至第 N 个未结束的 '{'

sentence 是以 . ! ? 为区格。paragraph 是以空白行为区格。
|)| N ) 向前 N 个句子
|(| N ( 向后 N 个句子
|}| N } 向前 N 段
|{| N { 向后 N 段

|w| N w 向前至第 N 个单词
|e| N e 向前至第 N 个单词词尾

|f| N f{char} 移动至右边第 N 次出现{char}的地方
|F| N F{char} 移动至左边第 N 次出现{char}的地方
|t| N t{char} 移动至右边第 N 次出现{char}之前
|T| N T{char} 移动至左边第 N 次出现{char}之前

fx 往右移动到 x 字符上
Fx 往左移动到 x 字符上
tx 往右移动到 x 字符前
Tx 往左移动到 x 字符后

CTRL-SHIFT-6回到上一个文件(e#)

杂类

插入模式下执行命令之后的光标位置问题

<ESC> 向前覆盖,^O向后覆盖, CTRL-\ CTRL-O 类似于 CTRL-O,但不移动光标

CTRL-O 命令有时有副作用: 如果光标在行尾之后,它会先被移动该行最后一个字符上。
在映射里,通常更好的方法是使用 <Esc> (先在文本中放一个 "x",<Esc> 这时总会把
光标放到它的上面)。或者使用 CTRL-\ CTRL-O,不过这时要注意光标可能移到行尾之外
的位置。

留言

Add a New Comment
or Sign in as Wikidot user
(will not be published)
- +
vim
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-Share Alike 2.5 License.