游标的移动
本节所述皆是在 common-mode(c-mode,在 vim 又名 normal-mode) 下的移动,原始的 vi 只能在 c-mode 移
动,在 insert-mode 只做文字的输入, 而不做游标的移动。当然 vim 及 elvis 的方向键是不论在那一种
mode 皆可移动自如。
基本的游标移动
h 左,或 Backspace 或方向键
j 下,或 Enter 或 +(要 Shift 键),或方向键
k 上,或 方向键或 -(不必 Shift 键)
l 右,或 Space 或方向键
Ctrl-f 即 PageDown 翻页。
Crtl-b 即 PageUp 翻页。
使用 hjkl 键的移动是为了使手不必离开打字区(键盘中央的部
位),
以加快打字的速度,如果各位不习惯,那就使用方向键吧!
Backspace 及 Space 的移动方式是到了行首或行尾时会折行,
但方向键或 hl 键的移动则在行首或行尾时您继续按也不会折
行。
转折换行的功能是 vim 的扩充功能,elvis 无此功能。
jk 及使用方向键的上下移动游标会尽量保持在同一栏位。
使用 Enter,+,- 的上下移动,游标会移至上(下)一行的
第一个非空白字元处。
好像有点复杂,各位就暂时使用方向键来移动就简单明白了!
等您爱上了 vim 后再来讲究吧。
进阶的游标移动
0 是数目字 0 而不是英文字母 o。或是 Hmoe 键,移至行首,(含空白字元)。
^ 移至第一个非空白字元,注意,要 Shift 键。
$ 移至行尾,或 End 键。要 Shift 键。
以上两个按键是源自规则表示式(regular expression),
在 regexp 中 ^ 是匹配行首,$ 是匹配行尾。
G 移至档尾(最后一行的第一个非空白字元处)
gg □至档首(第一行之第一个非空白字元处)
gg 是 vim 的扩充功能,在 elvis 或原始 vi 中可用 1G 来
移至档首(是数字 1 不是英文字 l)。
G 之原意是 goto,指移至指定数目之行首,如不指定数目,
则预设是最后一行。
w 移至次一个字(word)字首。当然是指英文单字。
W 同上,但会忽略一些标点符号。
e 移至前一个字字尾。
E 同上,但会忽略一些标点符号。
b 移至前一个字字首。
B 同上,但会忽略一些标点符号。
H 移至萤幕顶第一个非空白字元。
M 移至萤幕中间第一个非空白字元。
L 移至萤幕底第一个非空白字元。
这和 PageDown,PageUp 不一样,内文内容并未动,
只是游标在动而已。
n| 移至第 n 个字元(栏)处。注意,要用 Shift 键。n 是从头起算的。
:n 移至第 n 行行首。或 nG。
特殊的移动
) 移至下一个句子(sentence)首。
( 移至上一个句子(sentence)首。
} 移至下一个段落(paragraph)首。
{ 移至上一个段落(paragraph)首。
sentence 是以 . ! ? 为区格。paragraph 是以空白行为区格。
% 这是匹配 {},[],() 用的,例如您的游标现在在 { 上只要按 %,就会跑到相匹配的 } 上。写程
式时满好用的。
另还有一些 vim 的特殊按键,但这得留待最后才来讲述,否则各位恐怕会头昏眼花了。
基本编辑指令
这个单元就开始进入主题了。下编辑指令都是在 commond-mode (c-mode),就是您一进入 vim 时的模式,
只能下指令,不能键入文字。如果印象模糊,请瞄一下第一个单元的内容。这个单元说的是基本的指
令, 有些比较特殊的编辑指令,因为太有个性了,所以会独立成一个单元来说明。
进入 i-mode 的指令
i 在游标所在字元前开始输入文字(insert)。
a 在游标所在字元后开始输入文字(append)。
o 在游标所在行下开一新行来输入文字(open)。
I 在行首开始输入文字。
此之行首指第一个非空白字元处,要从真正的第一个字元处开始
输人文字,
可使用 0i 或 gI(vim)。
A 在行尾开始输入文字。
这个好用,您不必管游标在此行的什么地方,
只要按 A 就会在行尾等着您输入文字。
O 在游标所在行上开一新行来输入文字。
J 将下一行整行接至本行(Joint)。
并无相对的 split 功能,可在 i-mode 下按 Enter 来达成
,当然如果您熟 macro 的话,可自行定义。
使用 J 时,预设会消去本行的 EOL,且上下行接缝间会留下一个
空白字元,
这符合英文习惯,却对中文会造成困扰,欲不留空白字元,
可使用 gJ(大写 J)指令,但这是 vim 的扩充功能,elvis 不适
用。
请您随便找一个档案来试看看,光看文字说明太抽象了。
删除指令
x 删除游标所在处之字元。在 vim 及 elvis 亦可用 Del 键。
X 删除游标前之字元。不可使用 Spaceback 键。
vim 可以正确使用以上两个指令于中文,会删去一个中文字 elvis
则不行,
一个中文字要删两次,即使用 xx。
dd 删除一整行(delete line)。
dw 删除一个字(delete word)。不能适用于中文。
dG 删至档尾。
d1G 删至档首。或 dgg(只能用于 vim)。
D 删至行尾,或 d$(含游标所在处字元)。
d0 删至行首,或 d^(不含游标所在处字元)。
请回忆一下 $ 及 ^ 所代表的意义,您就可以理解 d$ 及 d^ 的动
作,
这就是 vi(m) 可爱之处。
取代及还原
r 取代游标所在处之字元。vi(m) 很有个性的,您在 c-mode 按了 r 她就会停在那里等主人键入所要
替代的字元,希望您这个当主人的,不要傻呼呼的也楞在那里,赶快键入您的新字元吧!:-)
vim 中可用于中文字,也就是可以替换一个中文字,elvis 则不
行。
当然您的 vim 是要设在 taiwan 的才行。怎么样!有没有看过如此
有个性的取代方式?ㄚ!r 就是 replace 啦!
R 取代字元至按 Esc 为止。
cc 取代整行内容。或大写 S 亦可。
cw 替换一个英文字(word),中文不适用。(change)
~ 游标所在处之大小写互换。当然不能用于中文。别忘了 Shift!
C 取代至行尾,即游标所在处以后的字都会被替换。或 c$。
c0 取代至行首,或 c^。
s 替换一个字元为您所输入的字串。和 R 不同,R 是覆盖式的取代,s 则是插入式的取代,您可
亲自实验看看。ㄟ!是小写的 s。
u 这个太重要了,就是 undo,传统的 vi 仅支援一次 undo,vim 及 elvis 就不只了,vim 是没有限制
的。
U 在游标没离开本行之前,回复所有编辑动作。
Crtl+r 这个也是很重要,就是 redo 键。
加上数目字
喔!骚到 vi(m) 的痒处了,这是 vi(m) 一个非常骚包的功能,只此一家别无分号(当然同源的 ed,sed 等
不在此限)。 就是您可以在大部份的指令前加上数目字,代表要处理几次的意思。以下用实例来说明
比较清楚。
5dd 删除游标所在处(含)起算以下五行内容。妙吧!
3r 按了 3r 后,您键入一个英文字,则三个字元皆会被您所键入的英文取代。很抱歉,这不能用
于中文。
5J 将五行合并成一行。
3x 删除三个字元。抱歉,不能用于中文。
5i A 然后按 Ecs,插入五个 A。中文也可以!
2i system Esc 插入 systemsystem。中文也可以!
5G 游标移至第五行,是从档首开始起算。
5l 移至右第五个字元处,当然 j 是可以用方向键取代的。所有移动指令(参考第二单元)都可以
加上数目字来控制,中文也通喔!elvis 当然是不能用于中文。
其它的指令和数目字结合,就留待各位去发掘吧!最重要的是请您亲自操作看看, 使用 vi(m) 常常要动
动脑筋,会有更妙的操作方式。
简单重排功能
〉〉 整行向右移一个 shiftwidth(预设是 8 个字元,可重设)。
〈〈 整行向左移一个 shiftwidth(预设是 8 个字元,可重设)。
:set shiftwidth? 可得知目前的设定值。:set shiftwidth=4
可马上重设为 4 个字元。shiftwidth 可简写成 sw。ㄟ,别忘了
Shift 键!
:ce(nter) 本行文字置中。注意是冒号命令!
:ri(ght) 本行文字靠右。
:le(ft) 本行文字靠左。
所谓置中、靠左右,是参考 textwidth(tw) 的设定。
如果 tw 没有设定,预设是 80,就是以 80 个字元为总宽度为标准
来置放。
当然您也可以如 sw 一样马上重设。
gqip 整段重排。中文会出槌!:-(
gqq 本行重排。
重排的依据也是 textwidth。这里的重排是指您键入文字时没有按
Enter 键,
就一直在 keyin,这样会形成一个很长的一行(虽然萤幕上会替
您做假性折行),
重排后,则会在每一行最后加入 EOL。gq 重排功能是 vim 才有的
功能。
复制(yank)
yank 是什么意思?有疑问的请查一下字典吧!就好像是中医治疗中的「拔罐」的意思啦 (是不是叫「拔
罐」?知道的朋友指正一下吧)!反正在 vi(m) 中,她就是复制 copy 的意思。 这在 vi(m) 的思考逻辑里,
就是「拔」yank 起来,「放」put 上去。其实复制的指令就是 y 一个而已, 为什么要独立成一个单元来
说明呢?因为 vi(m) 复制、贴上的功能实在太独特了, 再配合前面介绍的数目字,及 vi(m) 内部的缓冲
区来使用的话,您会发现, 原来 vi(m) 肚子里还暗藏着秘密武器。
指令说明
yy 复制游标所在行整行。或大写一个 Y。
2yy 或 y2y 复制两行。ㄟ,请举一反三好不好!:-)
y^ 复制至行首,或 y0。不含游标所在处字元。
y$ 复制至行尾。含游标所在处字元。
yw 复制一个 word。
y2w 复制两个字。
yG 复制至档尾。
y1G 复制至档首。
p 小写 p 代表贴至游标后(下)。
P 大写 P 代表贴至游标前(上)。
整行的复制,按 p 或 P 时是插入式的贴在下(上)一行。
非整行的复制则是贴在游标所在处之后(前)。
"ayy 将本行文字复制到 a 缓冲区
a 可为 26 个英文字母中的一个,如果是小写的话,原先的
内容会被清掉,如果是大写的话是 append 的作用,会把内
容附加到原先内容之后。
" 是 Enter 键隔壁的那一个同上符号(ditto marks)。
"ap 将 a 缓冲区的内容贴上。
缓冲区的术语在 vim 称为 registers,vim 扩充了相当多的
功能,有兴趣深入的朋友请 :h registers。您用 d、c、s、
x、y 等指令改变或删除的内容都是放在 registers 中的。
例如:您用 dd 删除的一行,也是可以使用 p 来贴上的。只
要是在缓冲区的内容都可以使用 p 来贴上,不是一定要 y 起
来的内容才能用 p。因此您认为 p 是 paste 也可以,认为是
put 可能较正确。
5"ayy 复制五行内容至 a 缓冲区。
5"Ayy 再复制五行附在 a 内容之后,现在 a 中有十行内容了!
ㄟ!不要我一直用 a 您就认为只有 a 可以用喔。26 个英文
字母都可以的,交叉运用下,您会发觉 vi(m) 肚量不小。
问题来了!忘记谁是谁的时候怎么办? :reg(冒号命令)就
会列出所有 registers 的代号及内容。您现在就试着按看看
咦!怎么还有数目字、特殊符号的缓冲区,原来您刚刚删除
(复制)的内容就预设放在 " 这个缓冲区,然后依序是
0,1,2,...9。也就是说您按 p 不加什么的话,是取出 " 缓
冲区的内容的。% 指的是目前编辑的档案,# 指的是前一次
编辑的档案。还有其它的呀!因为没什么重要,就请
:h registers 吧!registers 有个 "s" 结尾,不要搞错了,
而且 Tab 的补全键 vim 也支援的,也就是说您键入 :h regi
再按 Tab 键,vim 就会帮您补全,按了 Tab 后发现不是您要
的,那就继续按,总会出现您要的。:-)
Tab 补全的功能,elvis 也有,但叫出 registers 列表的命令
则没有,您得自行记忆在您的脑袋瓜子里。而且 elvis 的补全
能力并没 vim 强。
天大的指令
. 这是什么?ㄚ,是英文句点啦!没错,就是英文句点。什么意思?重复前次的编辑动作。 这个指令太
高明了,只要是编辑动作(移动游标不算,冒号命令也不算) 都可以按英文句点来重复,要重复几次
都可以。
例如:您按了 yy,然后按 p 就会复制、贴上一整行,如果要重复这个动作的话, 就可以按 . ,也可以
把游标移到其它地方后再按。其它 dd,dw,r,cw 等编辑指令都可以这样来重复。 如果您要重复做某
些编辑动作时,千万千万一定要想到有这么一个英文句点重复指令。ㄚ,拜托啦!您一定要常用这个
指令。
疑难杂症
1.那 mouse 中键的剪贴功能还有吗?当然还有,不管在 console 或 X terminal 中都照用不误。 当然在
windows 下的话就不能用了,可以用 Shift-Insert 来代替。Ctrl-v 在 vim 中另有作用, 在 windows 下
就不必去麻烦它了。
2.ㄟ,我从.netscape 用 mouse copy 东东过来的时候,常常都搞得天下大乱耶! 要设成 :set paste,预
设是 map 至 F9 键的,您要 copy 之前先按一下 F9,copy 完后再按一次 F9 来回复。 这是 vim 的扩
充功能,elvis 没有。那在 elvis 怎么办?只好 :set noai 了。在 GUI 的版本应不会有这种情形。
set 的功能先不必去理它,往后会有一个单元专门讨论。
朋友!您睡着了吗?不要被吓到了,您只要开个档案,亲自操作一下就能心领神会。 那用 mouse 不是
更方便吗?不见得,yyp 来复制贴上一整行比较快,还是用 mouse 来拉比较快? 您可以试看看。
寻找/替换
搜寻、替换的功能几乎是每个编辑器必备的功能,那在 vi(m) 中有没有特殊的地方呢? 当然有,您忘
了,vi(m) 是个性十足的编辑器。最特殊的地方是和规则表示式 (regular expression,简称 regexp) 结合在一
起。简单的说她是一种 pattern 的表示法, 在执行动作,如寻找或替换,就会依据这个 pattern 去找,所
有符合 pattern 的地方就会执行您所下的动作。 在这个单元里不讨论 regexp,会另立一个单元来探讨,
以免搞得头昏脑胀。目前就暂不使用 regexp, 您要找什么就直接键入什么就对了。
寻找
/ 在 c-mode 的情形下,按 / 就会在左下角出现一个 /,然后键入您要寻找的字串,按个 Enter 就会
开始找。
? 和 / 相同,只是 / 是向前(下)找,? 则是向后(上)找。
n 继续寻找。
N 继续寻找(反向)。
更方便的寻找操作(vim 才有)
* 寻找游标所在处之 word(要完全符合)。
# 同上,但 * 是向前(下)找,# 则是向后(上)找。
g* 同 * ,但部份符合即可。
g# 同 # ,但部份符合即可。
n,N 之继续寻找键仍适用。
替换(substitute)
:[range]s/pattern/string/[c,e,g,i]
range 指的是范围,1,7 指从第一行至第七行,1,$ 指从第一行至最后一行,也就是整篇文章,也可以 %
代表。
还记得吗? % 是目前编辑的文章,# 是前一次编辑的文章。
pattern 就是要被替换掉的字串,可以用 regexp 来表示。
string 将 pattern 由 string 所取代。
c confirm,每次替换前会询问。
e 不显示 error。
g globe,不询问,整行替换。
i ignore 不分大小写。
g 大概都是要加的,否则只会替换每一行的第一个符合字串。
可以合起来用,如 cgi,表示不分大小写,整行替换,替换前
要询问是否替换。
[实例] :%s/Edwin/Edward/g
这样整编文章的 Edwin 就会替换成 Edward。
更进阶的寻找、替换的例子在说明 regexp 的时候还会再详述。 目前只知道最基本的用法就可以了!其
实光这样就非常好用了。:-)
书签功能
这又是 vi(m) 的一个秘密武器,简单的说,您可以在文章中的某处做个记号(marks), 然后跑到其它地方
去编辑,在呼叫这个 mark 时又会回到原处。妙吧!
mx x 代表 26 个小写英文字母,这样游标所在处就会被 mark。
`x 回到书签原设定位置。
` 是 backward quote,就是 Tab 键上面那一个。
’x 回到书签设定行行首。
’ 是 forward quote,是 Enter 键隔壁那一个。
vim 对于书签的扩充功能
小写字母 只作用于单一档案内。
大写字母 可作用于编辑中之各档案间。
数目字 可作用于前次编辑的十个档案。
数目字的用法比较特殊,’0 是回到前一次编辑档案中离开
前的最后位置,’1 则是回到前二次编辑档案的最后位置,
依此类推。您不必使用 m 来标示,vim 会自动记忆。
很玄吧!其实这是 viminfo 的功能,您要认真追究的话,
请 :h viminfo-file-marks。viminfo 关掉,就没这个功能了!
所谓前次指的是前次启动的 vim。
:marks 得知目前所有书签的列表。
叫档、存档、紧急回复
ㄟ,是不是在灌水呀!怎么开个档也成一个单元?那您就错了, 在 vi(m) 里叫档的花样可多了,而且又
可以多档编辑, 各编辑中的档案还可以互通讯息,这里面学问可大著呢!vim 就更骚包了, 也学人家
档案可以加密,虽说是噱头,但也还满好用的。
开档的一些花招
vim + 档名
这样开档后,游标会落在档案最后一行的行尾,在档案屁屁后干什么呢?方便您可以继续编辑
嘛!
vim +n 档名
游标会落在第 n 行的行首。
vim +/string 档名
还记得吗? / 就是寻找指令,这样进入档案后游标就会落在第一个找到的 string 上, 还可以按 n
继续找 string 喔!哦,string 还可以使用 regexp 来表示喔。
多档编辑
多档编辑会有两种情形,一种是在进入 vim 前所用的参数就是多个档(这种情形称为 argument list)。
另一种情形是进入 vim 后另外再开其它的档(称为 buffer list)。不过都可以统称为 buffer。
:n 编辑下一个档案。
:2n 编辑下二个档案。
:N 编辑前一个档案。
注意,这种用法只能用于 argument list 的情形。
:e 档名 这是在进入 vim 后,在不离开 vim 的情形下再开其它档案。 只要您要编辑的档案是在目前
目录,Tab 补全键还是可以使用。
:e# 或 Ctrl-^ 编辑前一个档案,用于两档互相编辑时相当好用。
这种用法不管是 argument list 或 buffer list 档案间皆可使用。
还记得吗? # 代表的是前一次编辑的档案。
:files 或 :buffers 或 :ls 会列出目前 buffer 中的所有档案。
在 elvis 中可使用 :b 来叫出 buffers。
在 buffers 中,减号 - 表示这个 buffer 并未载入,不过,
不必担心,载入相当快速的。加号 + 表示这个 buffer
已经修改过了。
:bn buffer next。
:bl buffer last。
以上两个指令 elvis 不适用。
:b档名或编号 移至该档。
在 :ls 中就会出示各档案的编号,这个编号在未离开 vim 前是不
会变的。
这个指令 elvis 也是可以使用。
当然 :e#编号 也是可以的,这样的用法则是所有 vi clone 都通用
了。
如果您是使用 vim 的 GUI,那就在功能表上就会有 Buffers 这个选
项,
可以很容易的知道及移动各 buffer 间。
:bd(elete)
buffer 在未离开 vim 前是不会移除的, 可使用这个指令移除。其实移除她干什么呢?vim 是您在
叫用时才会载入的,因此这些 buffers 并不是像 cache 一般要占记忆体的。
:e! 档名
这样也是会开档,但会放弃目前编辑档案的改变,否则如果档案已有变动, vim 预设是不让您随
便离开的。:e! 后不接什么的话,代表舍弃一切修改,重新载入编辑中档案。
:f 或 Ctrl-g
显示目前编辑的档名、是否经过修改及目前游标所在之位置。
:f 档名
改变编辑中的档名。(file)
:r 档名
在游标所在处插入一个档案内容。(read)
:35 r 档名
将档案插入至 35 行之后。
gf
这是 vim 的特殊叫档法,会叫出游标所在处的 word 为名的档案,当然,这个档案要在目前目录
内,否则会开新档案。
哦!好像有点给他复杂,主要原因是偶文笔不好啦!不过您何不选个顺手的来用就可以了, 选定了,
以后就是使用他,这样就不会那么复杂了。:-)
离开
:q 如本文有修改而没存档,会警告,且无法离开。(quit)
:q! 舍弃所有修改,强迫离开。
:wq 存档后离开。纵使档案未曾修改也是会再存一次档。
:x 也是存档后离开,但如果档案没有修改,则不会做存档的动作。
ZZ 和 :x 完全一样,随您高兴用哪一个。
:w 档名 另存他档。不加档名就是写入原档。(write)
:q 及 :q! 是对目前编辑中的档案作用,如果多档编辑的情形
并不会离开 vim,这时可下 :qa 或 :qa! 来整个离开 vim。
a 就是 all 的意思。
vim 的加密功能
vim -x [档名]
这样进入 vim 后会要求输入密码。以后加密过的档案由 vim 开启时会自动要求输入密码。否则无法开
启。其它的编辑器当然是无法开启的。
进入 vim 编辑档案中,临时想加密,可用 :X 指令。
小心!vim 一开档就会有个 .档名.swp 这个档,是为了紧急回复用
的,
一般是在您所开档案的所在目录,这是个隐藏档,ls 要有 -a 参数
才看得到,
您加密的功能并没有作用在这个 swp 档,因此 root 还是知道您在
写些什么关于他的坏话的。:-) 当然啦!山不转,路转,路不转,
人转,
您也是可以把 swap 的功能关掉的 :set noswf 就行了!但如果您编
辑的是
大档案,则不建议您把 swap 关掉,这样会很吃记忆体的。
elvis 的话,其暂存档是统一集中存放在 /var/tmp/*.ses,
权限是档案所有者始能读写。vim 的早期版本,其 *.swp
档是依原档案的权限来设定的,最近的版本则从善如流,
已经改成档案所有人始能读写,就是 -rw------- 啦!
紧急回复
vim -r 档名,或进入 vim 后,下 :recover 档名,来回复。