vi 使用整理

为什么80%的码农都做不了架构师?>>>   hot3.png


一.假设你已开始喜欢vi了...

二. 开启档案, 关闭档案
vi 檔名  开启档案
: 进入命令列的方法
q 离开 (命令列)
wq 存盘然后离开 (命令列)
q! 放弃存盘, 强迫离开 (命令列)
ZZ 存盘然后离开 (不在命令列使用)
:e 檔名 在 Vi 中开启档案
三. Vi 的操作模式:
Vi 有二种主要的操作模式, ESC 键为单向的切换键(由本文输入模式回到编辑命令模式)
编辑命令模式 : 要 vi 做一些特定目的的动作. 如插入,附加,取代,修改,删除,移动光标,搜寻等等. 若是存盘等动作, 则需在命令列中下达, 欲切换至命令列, 需先按 :
本文输入模式 : 在此模式下, 任何字符, 皆被视为输入的数据. 
一开始进入 Vi 之后, 即进入编辑命令模式, 你输入的每一个字符, 皆被预视为一个指令. 有效的指令会被接受, 若是无效的指令, 会产生 beep beep 声, 以示警告.
若想做输入的动作, 必须切换为本文输入模式, 切换的方法, 只要单按一个特殊意义的字符键即可, 如下所示:
按 i 或 I 插入状态
按 a 或 A 附加状态
按 R 取代状态R 会进行连续字符取代
按 s 或 S 删除一个字符;删除光标所在那一列
按 cw, c2b, c$, c0 修改状态
按 o 或 O 新增空白列
你不必一下子全用上, 只要会 i, a, o 这个三个模式即可胜任愉快, 因为大部份时候, 你也只用这三个.
OK, 现在你可以试着在本文输入模式下, 键入一些资料看看. 然后, 按 ESC 切换回编辑命令模式.
四. 移动光标:
Vi 为了适用于各种不同的终端机模式, 因此以字键的方式来操控光标.
k j h l 上 下 左 右
Enter 换列
w b 往前一个 word ; 倒退一个 word
0 $ 至该列开头 ; 至该列尾端
+ - 往下一列; 往上一列
请记住一个要诀: 
在 Vi 中, 大部份的命令都可以在其前面加上数字, 该数字表示重复该命令的次数.
例如: 8l 表示往右移动 8 个字符, 3w 表示往前移动三个 word, 2b 表示倒退 2 个 word
注: word 的定义, 连续英数字元形成一个 word, 而其它特殊符号则每一个字符便是一个 word(除非连续特殊字符), 例如: --classify 中含有 2 个 word, 一个是 -- ; 一个是 classify
而 -x, 则有 3 个 word.
在特殊的终端机模式下, 方向键也是可以使用的. 如 linux 或 vt100. 
其实大部份时候, 你仍可以保有使用方向键的习惯. 但大概只有 local 下才能使用 PgUp , PgDn, End, Home 等键喔!
不过, 若你所使用的终端机模式不支持方向键, 那么上表中的按键, 就相当重要了.
五. 卷页:
^f 往下一页 (forward)
^b 往上一页 (before)
^d 往下半个屏幕(down)
^u 往上半个屏幕(up)
六. 跳列:
你可以指定跳至某一列位置. 跳动之前, 先查看一下目前所在列数是多少.
^g 可以显示目前的位置, 如: "ls.txt" line 53 of 264 --20%-- col 16-23 
上面表示, 目前是在第 53 列, 全部共有 264 列, 占该档百分之20的位置, 目前的光标, 实际是在第23行, 但只算成第16行, 因为中间有使用 tab 键.
80G 或 80gg 跳至第 80 列
G 跳至文件尾
gg 跳至文件头
七. 删除: (但不会进入本文输入模式)
x 删除一个字符
dd 删除一行
r 取代一个字符
以上皆针对光标目前的所在位置产生作用. 
还有 dw, db, de, d0, d$ 等命令, 但你不须一下子全用上. 上表中这三个够用了.
记住一个要诀: Vi 的命令繁多, 但你真正用上手的不必多, 而且这些也就够了.
八. undo (回复动作):
若你对上一个动作反悔了, 可以使用 undo 的功能:

u 取消上一个动作所产生的改变

U 取消光标所在那一列所有的改变
:e! 取消所有的改变, 回复至未修改之前
九. 关键词搜寻/取代:
/ 关键词 往下搜寻关键词
? 关键词 往上搜寻关键词
n 重复搜寻命令(不管往下或往上)
N 和 n 相反方向
cw字符串 以该字符串取代原有的关键词
n. 继续取代该字符串的动作
%s/目标/取代/g 将目标字符串全换成取代字符串
十. 选取、复制与搬移:
Y 或 yy 选取光标所在那一列
5Y 或 5yy 选取光标列所在共5列(5 只是一个例子, 可改用其它数字)
p 将选取的内容, 复制至光标之后
P 将选取的内容, 复制至光标之前
cw, x, dd 等删除命令 会将被删除的内容放入 buffer 中, 配合 p 或 P 即可做出搬移的效果.
十一. 暂时跳出 Vi:
在编辑过程中, 你可能想要执行其它命令, 方法如下:
:! 命令 执行该令命
:sh 暂时跳出 Vi, 欲回 Vi 按 ^d 或 exit

vI技巧:
shift + a移到本行尾并编辑
gg跳到文首
G跳到文尾
0跳到行首
$跳到行尾
w跳到下一个word
ndw 或 ndW 删除光标处开始及其后的 n-1 个字符。 
d0 删至行首。 
d$ 删至行尾。 
ndd 删除当前行及其后 n-1 行。 
x 或 X 删除一个字符。 
Ctrl+u 删除输入方式下所输入的文本。 
^R 恢复u的操作 
J 把下一行合并到当前行尾 
V 选择一行 
^V 按下^V后即可进行矩形的选择了 
aw 选择单词 
iw 内部单词(无空格) 
as 选择句子 
is 选择句子(无空格) 
ap 选择段落 
ip 选择段落(无空格) 
D 删除到行尾 
x,y 删除与复制包含高亮区 
dl 删除当前字符(与x命令功能相同) 
d0 删除到某一行的开始位置 
d^ 删除到某一行的第一个字符位置(不包括空格或TAB字符) 
dw 删除到某个单词的结尾位置 
d3w 删除到第三个单词的结尾位置 
db 删除到某个单词的开始位置 
dW 删除到某个以空格作为分隔符的单词的结尾位置 
dB 删除到某个以空格作为分隔符的单词的开始位置 
d7B 删除到前面7个以空格作为分隔符的单词的开始位置 
d) 删除到某个语句的结尾位置 
d4) 删除到第四个语句的结尾位置 
d( 删除到某个语句的开始位置 
d) 删除到某个段落的结尾位置 
d{ 删除到某个段落的开始位置 
d7{ 删除到当前段落起始位置之前的第7个段落位置 
dd 删除当前行 
d/text 删除从文本中出现“text”中所指定字样的位置, 
一直向前直到下一个该字样所出现的位置(但不包括该字样)之间的内容 
dfc 删除从文本中出现字符“c”的位置,一直向前直到下一个该字符所出现的位置(包括该字符)之间的内容 
dtc 删除当前行直到下一个字符“c”所出现位置之间的内容 
D 删除到某一行的结尾 
d$ 删除到某一行的结尾 
5dd 删除从当前行所开始的5行内容 
dL 删除直到屏幕上最后一行的内容 
dH 删除直到屏幕上第一行的内容 
dG 删除直到工作缓存区结尾的内容 
d1G 删除直到工作缓存区开始的内容  


/ 查找
n 查找下一个

N 查找上一个

set number 显示行号
set mouse=a 显示鼠标
set ts=4 设置tablespace是4个字符,默认为8个
set autoindent 可以自动缩进

" 搜索

/joe/e : 设置光标到匹配"joe"的末尾

/joe/e+1 : 设置光标到匹配"joe"的末尾再后移一位

/joe/s-2 : 设置光标到匹配"joe“的开头再前移两位

/^joe.*fred.*bill/ : 匹配以'j'开头且"joe"到"fred"到"bill"之间至少有一个字符

/^[A-J]\+/ : 搜索'A'到’J‘重复两次以上的开头行

/begin\_.*end : 多行匹配

/fred\_s*joe/i : 可以是任何空白字符包括\n,\t等等

/fred\|joe : 搜索fred或者joe

/.*fred\&.*joe : 搜索同时包括fred跟joe的行

/\/i : 搜索独立的单词fred

/\<\d\d\d\d\> : 搜索独立的4位数字

/\D\d\d\d\d\D : 搜索6位字符串中间4位数字前后两位不能为数字

/\<\d\{4}\> : 同/\<\d\d\d\d\>

" 查找空行

/^\n\{3} : 匹配三连续的空行

" 使用正则表达式组查找

/\(fred\).*\(joe\).*\2.*\1

" 正则表达式重复

/^\([^,]*,\)\{8}

" visual searching

:vmap // y/" : visually模式下的键盘映射,把//映射成匹配当前选中的文本

:vmap // y/=escape(@", '\\/.*$^~[]') : 包括空白字符

" \zs 和 \ze 匹配原 :h /\zs

/<\zs[^>]*\ze> : 匹配尖括号中的内容

" 零宽度匹配 :h /\@=

/<\@<=[^>]*>\@= : search for tag contents, ignoring chevrons

/<\@<=\_[^>]*>\@= : search for tags across possible multiple lines

" 多行查找 \_ 的意思是包括换行符

/ : 匹配结尾的所有内容

/fred\_s*joe/i : 匹配fred开始到joe,之间一定得是空白字符

/bugs\(\_.\)*bunny : 匹配所有bugs到bunny的字符串

:h \_ : help

" 查找函数声明,nmap为normal模式下的键盘映射

:nmap gx yiw/^\(sub\function\)\s\+"

" 查找多个文件

:bufdo /searchstr/ : 在多个文件缓冲区里执行查找

" 更好的多文件查找定位方法

:bufdo %s/searchstr/&/gic : 在多个文件缓冲区里查找,按下n停止

" 怎样不使用 / 来查找网址

?http://www.vim.org/ : 向后查找

" 查找指定字符以外的字符串

/\c\v([^aeiou]&\a){4} : 查找4个辅音字母

----------------------------------------

#替换

:%s/fred/joe/igc : 普通替换命令

:%s/\r//g : 删除 DOS 的换行符 ^M

" 你的文本文件是否乱七八糟的排成一行?使用如下命令

:%s/\r/\r/g : 转换 DOS 回车符 ^M 为真正的回车符

:%s= *$== : 删除行尾空白

:%s= \+$== : 同上

:%s#\s*\r\?$## : 删除尾部空白和dos换行符

:%s#\s*\r*$## : 同上

" 删除空行

:%s/^\n\{3}// : 删除连续3个空行

:%s/^\n\+/\r/ : 压缩空行,多个替换为一个

%s#<[^>]\+>##g : 删除html的tag部分

" IF YOU ONLY WANT TO KNOW ONE THING

:'a,'bg/fred/s/dick/joe/igc : 非常有用

# 译释:''a,''b指定一个范围:mark a ~ mark b

# g//用一个正则表达式指出了进行操作的行必须可以被fred匹配

# 看后面,g//是一个全局显示命令

# s/dick/joe/igc则对于这些满足条件的行进行替换

" 复制列

:%s= [^ ]\+$=&&= : 复制最后一列

:%s= \f\+$=&&= : 一样

:%s= \S\+$=&& : 晕,还一样!

" 记忆(反向引用)

:s/\(.*\):\(.*\)/\2 : \1/ : 将两个字段颠倒

:%s/^\(.*\)\n\1$/\1/ : 删除重复行

" 非贪婪匹配 \{-}

:%s/^.\{-}pdf/new.pdf/ : 删除第一个pdf

" use of optional atom \?

:%s#\<[zy]\?tbl_[a-z_]\+\>#\L&#gc : lowercase with optional leading characters

" 跨越尽量多的行

:%s/// : 删除多行注释

:help /\{-} : 查看非贪婪匹配的更多帮助

" 使用寄存器替换

:s/fred/a/g : 将fred替换为寄存器a里的内容

:s/fred/asome_texts/g

:s/fred/\=@a/g : better alternative as register not displayed

" 在一行里写多种命令

:%s/\f\+\.gif\>/\r&\r/g | v/\.gif$/d | %s/gif/jpg/

:%s/a/but/gie|:update|:next : 当使用 @: 来重复

" 或运算

:%s/suck\|buck/loopy/gc : 替换suck或者buck(这里|不是管道)

" 调用vim函数

:s/__date__/\=strftime("%c")/ : 将__date__替换成当前日期,使用strftime函数

" 处理列,替换所有在第三列中的str1

:%s:\(\(\w\+\s\+\)\{2}\)str1:\1str2:

" 交换第一列跟第四列

:%s:\(\w\+\)\(.*\s\+\)\(\w\+\)$:\3\2\1:

" 过滤form中的内容放在寄存器里

:redir @*|sil exec 'g#<\(input\|select\|textarea\|/\=form\)\>#p'|redir END

:nmap ,z :redir @*sil exec 'g@<\(input\select\textarea\

/\=form\)\>@p'redir END

" 两位以上的数字减三(带进位。这个命令挺有趣)

:%s/\d\+/\=(submatch(0)-3)/

" 包含loc或者functions的行中的数字加6

:g/loc\|function/s/\d/\=submatch(0)+6/

" 比上面更好的方法

:%s#txtdev\zs\d#\=submatch(0)+1#g

:h /\zs 查看帮助

" 前缀为gg的数字加6

:%s/\(gg\)\@<=\d\+/\=submatch(0)+6/

:h zero-width 查看帮助

" 替换一个特定字符串为数字

:let i=10 | 'a,'bg/Abc/s/yy/\=i/ |let i=i+1 # 将yy转换成10,11,12等等

" 比上面的更精确

:let i=10 | 'a,'bg/Abc/s/xx\zsyy\ze/\=i/ |let i=i+1 # 将xxyy 转换成 xx11,xx12,

xx13

" find replacement text, put in memory, then use \zs to simplify substitute

:%s/"\([^.]\+\).*\zsxx/\1/

" Pull word under cursor into LHS of a substitute

:nmap z :%s#\<=expand("")\>#

" Pull Visually Highlighted text into LHS of a substitute

:vmap z :%s/\<*\>/

----------------------------------------

" all following performing similar task, substitute within substitution

" Multiple single character substitution in a portion of line only

:%s,\(all/.*\)\@<=/,_,g : replace all / with _ AFTER "all/"

" Same thing

:s#all/\zs.*#\=substitute(submatch(0), '/', '_', 'g')#

" Substitute by splitting line, then re-joining

:s#all/#&^M#|s#/#_#g|-j!

" Substitute inside substitute

:%s/.*/\='cp '.submatch(0).' all/'.substitute(submatch(0),'/','_','g')/

----------------------------------------

" 全局显示命令

:g/gladiolli/# : 查找并显示匹配的行号

:g/fred.*joe.*dick/ : 显示所有含有 fred,joe & dick的行

:g/\/ : 显示单一单词fred

:g/^\s*$/d : 删除所有空行

:g!/^dd/d : 删除不含字符串''dd''的行

:v/^dd/d : 同上

:g/fred/,/joe/d : 删除所有的从fred到joe

:g/-------/.-10,.d : 以-------为标记删除之前的10行

:g/{/ ,/}/- s/\n\+/\r/g : 删除 {...}之间的空行

:v/\S/d : Delete empty lines (both types)

:v/./,/./-j : 压缩空行

:g/^$/,/./-j : 同上

:g/

:g/^/put_ : 双倍行宽 (pu = put)

:g/^/m0 : 颠倒文件 (m = move)

:'a,'bg/^/m'b : 颠倒选中的 a 到 b

:g/^/t. : 重复行

:g/fred/t$ : 拷贝行从fred到结尾

:g/stage/t'a : 拷贝行从stage 到 marker a(a为标记的位置)

:g/\(^I[^^I]*\)\{80}/d : 删除最少包含80个tab的行

" perform a substitute on every other line

:g/^/ if line('.')%2|s/^/zz /

" match all lines containing "somestr" between markers a & b

" copy after line containing "otherstr"

:'a,'bg/somestr/co/otherstr/ : co(py) or mo(ve)

" as above but also do a substitution

:'a,'bg/str1/s/str1/&&&/|mo/str2/

:%norm jdd : 隔行删除

" 增加数字 (键入 )

:.,$g/^\d/exe "norm! \": 增加从当前行首到结尾的数字

:'a,'bg/\d\+/norm! ^A : 增加数字

" 保存全局命令的结果 (注意必须使用添加模式) 你需要使用 qaq 清空寄存器a.

"save results to a register/paste buffer 存储结果到 寄存器/粘贴 到 a

:g/fred/y A : 添加配备行到寄存器到 a

:g/fred/y A | :let @*=@a : 放入复制缓冲区

:let @a=''|g/Barratt/y A |:let @*=@a

:'a,'b g/^Error/ . w >> errors.txt

" 复制每一行,然后在复制出来的每一行两侧加上一个 print '复制出来的内容'

:g/./yank|put|-1s/'/"/g|s/.*/Print '&'/

" 用文件中的内容替换字符串,-d 表示删除“标记”

:g/^MARK$/r tmp.ex | -d

" display prettily

:g//z#.5 : display with context

:g//z#.5|echo "==========" : display beautifully

" Combining g// with normal mode commands

:g/|/norm 2f|r* : replace 2nd | with a star

"send output of previous global command to a new window

:nmap :redir @a:g//:redir END:new:put! a

----------------------------------------

" 全局命令和替换命令联姻 (强大的编辑能力)

:'a,'bg/fred/s/joe/susan/gic : 可以使用反向引用来匹配

:g/fred/,/joe/s/fred/joe/gic : non-line based (ultra)

----------------------------------------

" 先找fred,然后找joe

:/fred/;/joe/-2,/sid/+3s/sally/alley/gIC

----------------------------------------

" create a new file for each line of file eg 1.txt,2.txt,3,txt etc

:g/^/exe ".w ".line(".").".txt"

----------------------------------------

" Absolutely essential

----------------------------------------

* # g* g# : 查找当前光标下的单词(单个单词) () (向前/向后)

% : 匹配括号 {}[]()

. : 重复上次操作

@: : 重复上次的命令

matchit.vim : 适%能匹配

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部