VI操作实例

使用 vi 如何以简单有条理的方式来重复处理档案中的资料,并在不更动原档案的情况下,将这些数据存放到新档案中?

严格说来,这样的处理作业,应选择像 sed,awk 这样的工具,在处理效率上比较好;如果,处理需求单纯的话,grep 也足以应付。但那样的选择,通常是在处理流程已经相当成熟,且有必要经常性的重复使用之下,所做的工具选择。在突发性且处里模式尚未厘清前,使用 vi 是较具弹性的选择。

我以一个整理 httpd access_log 来作说明。

2001/12/16 凌晨,我刚好在主机上做点测试。当时的网络有点忙,我使用 netstat -ct 看了一会儿网络的状况,知道目前 httpd 有几位访客。一时兴起想看看她们来看什么,于是我使用 vi 去看了一下 Apache access_log,意外地发现,同一时间,我的同胞 202.102.141.56 正在扫描主机的 httpd server。再观察一下 netstat -ct 的讯息,我发觉她还没有完全做完。心想不应该打断人家的工作。当时人已有点困了,所以我退出了 vi 并赶紧继续做我的事情。不久,周公他老人家就来抓我出公差,做他最近经营的 playboy 网站。虚拟实境的欧,采会员制,非十八岁以下的梦遗才俊不收。我只有做苦工的份,没资格加入。

隔日自然醒来,打开计算机,先来上一段 Queen We are the champions 加上一杯咖啡。突然想起凌晨未完成的观察,马上用 vi 再查看 access_log。乖乖!不是一个,前后共三位青年才俊上网。此时在 vi 模式下,我想分别将三位的数据从 access_log 档案中分离出来,建立三个个别档案。这种想法,以前不曾想过!一时卡住了,不知道该怎么做?拿起笔来,在纸上写下了"如何"挪移"这几个字。喝完我的咖啡后,趴在桌上小咪一下..才一下,就被周公槌醒,我看着"挪移"两字,方法找到了。

# vi access_log

我使用 vi 指令进入了要编辑的 access_log 档案中。因为没有加上任何特殊选项,所以光标会在第一行的位置。接着,我打算将有为青年一号,地址是 202.102.141.56,所遗留的拜访纪录全部挪移到档案的最末端。指令如下:

:g/202.102.141.56/mo$

该行指令其中 g 代表 global,是整个档案的意思。在 :g/ 后面的是要搜寻的字符串,我代入的是 202.102.141.56,也就是有为青年一号。最后 mo$ 其实是 ex 编辑器的指令,mo move 搬移;$ 则代表最后一行的意思。所以这行指令做的就是,将档案从上到下检查内含有 202.102.141.56 的每一行,找到了就将该行搬移到档案的最后一行。执行完毕后,光标会停留在最后一行。

这样,我就达到将"有为青年一号"的拜访数据透析出来的目的了。当然,我是可以继续使用相同的手法整理有为青年二、三号,不过我的想法是单独存盘,所以这时还不需要处理。紧接着我要删除无关的数据。

:/202.102.141.56

因为光标已在最后一行,搜寻会自动跳回第一行重头开始寻找字符串。藉此,我已将光标移动到"有为青年一号"数据的开头位置。光标以上的是我不需要的数据,以下则是打算存档的内容。

接着我将光标往上跳一行(也就是按一下 k ),然后清除该行到第一行的所有数据。

d1G

清除后留下的就是"有为青年一号"全部数据。

:w Timmy-no1

将现存的结果另存新档,档名为取作 Timmy-no1(Timmy 一字,来自于艾西莫夫与席维伯格合着的某本科幻小说,是一位非常特殊的主角)

到此,事情算到一个段落。因为我还要原来的数据,在一般状况下,我会选择 :q! 放弃存档并退出 vi 。但因为我还需继续透析出"有为"青年二、三号"的数据。所以我得回复原档案的数据,简单如下

:e!

这个动作,我个人比较喜欢称为"倒带"。好了,倒完带后,档案的内容就回复到上次存盘的状态,我因为没存过档,所以便回复到进入 vi 时的原数据,接着就可以用先前的做法处理"青年二、三号"了。最后记得用 :q! 退出 vi 就可以了。

做完这件事之后,我满足地睡个回笼觉。梦里,周公对我说:干的好呀,孩子。别忘了睡醒后把新会员的资料,E-mail 给我呦。下回嘉奖你享受一下"虚拟实境"的滋味。现在白天,既然来了,就好好地加班,建网页去.....,还不快去!


传统的 vi 指令,不支持多重窗口编辑。所以无法用一只 vi 程序同时开启两个档案做数据交换、转移的编辑。但这点并没有太大的不便,因为替代的方法也很简单。只要善用 vi 程序的具名缓冲区,先将 A 档案的数据暂存起来,然后继续编辑 B 档案,再呼叫出来即可。

vi 程序的运作而言,使用 d (delete) y (yank) 都会将数据放入具名的 buffer 中。但对本文的需求来说,我自己绝对不会选择 delete 来做,虽然做得到,但太危险。所以唯一且正确的选择是使用 yank。她支持小写字母 a ~ z 命名的具名缓冲区供使用者运作。现在仔细想想,似乎我从不曾嫌过 26 个不够用?但她毕竟是一个相当有限的限制。

接下来是我实际运作的例子。每天系统的 message 档案,总会有一些异常的信息。这些讯息虽多半具有规律性,但仍然会有无法掌握的情况出现。由于我的系统服务非常单纯,所以我习惯使用 vi 查看每天发生的事情。检视的过程中如果有异样或自己搞不清楚的警讯,我就先将她存入具名缓冲区中,等到全部检视完毕后,再决定如何处理。

现在,假设我要开始检视 messages 档案中有关于 12 24 日的纪录;

# vi +/"Dec 24" messages

光标会停在我要的第一笔资料上。我往下检视当天纪录,不久发现连续三行资料有异样,我把光标停在第一行的位置,下指令先将她们放入具名缓冲区中;

"q3yy

如此,三行数据就会存入 q 缓冲区内。再往下检视,又发现零散的几行异常都与某 IP 有关。因此我将 IP 的数据。一样我先将光标停在该 IP 的开头位置,然后再下指令;

"w8yw

该行的意思是存 8 ""(word)存到 w 缓冲区内。xxx.xxx.xxx.xxx IP 的固定格式,其中的 dot 在定义上是特殊符号,视同一个""(word),所以像 IP 这样的格式在表示上用 8 ""(word)

往下再找到的,我都以相似的方法将她们存在不同的缓冲区内。最后我呼叫我自己的异常纪录档案,准备将数据储存起来;

:e + strange2k112

在呼叫时我加上选项 "+",所以我光标会停来在最后一行。我开始顺序地将存放在具名缓冲区的数据 put strange2k112 这个档案中;

"qp
"wp
"ep
....


小写的 p 会将数据放在光标之后;想放在光标之前使用大写的 P 即可。


在编辑的过程中,早已删除的数据,突然想再找回来。这样的事情难免会偶而发生。有人会选择一路 undo 回去,甚至完全放弃所有的编辑,我个人并不认为这是好的做法。因此如过可能的话,我还是想找回来,如果找得回来的话。要想这样做,首先就必须清楚,vi 程序是如何处理 delete 的数据。

vi
程序规划了 9 个具名缓冲区供 delete 做数据暂存。缓冲区的名称就是数字 1 9。数据采"先进先出"的模式存放。也就是说,你清除一笔数据,它会被放入缓冲区 1,原先缓冲区 1 内的数据会被新进的数据挤到缓冲区 2,以此类推,可以想象,缓冲区 8 的数据挤进缓冲区 9 后,原先缓冲区 9 的数据将会被丢弃。而被丢弃的数据,将无法使用呼叫具名缓冲区的方式挽救回来。

清楚其运作方式后,你将发现,要明确地掌握资料在哪一个缓冲区内,实在是一件高难度的事情!原因在清楚不过,谁会去记这码事?就算有人刻意去记恐怕也不是一件轻松的事。坦白说,打死我,我也不会去记!

所以万一事情发生了,想使用这个方法找回来,心里必须有数,只有九个缓冲区,可不可能还在?如果可能的话再用。得用上时,土法炼钢的方法是,由呼叫缓冲区 9, 8, 7...一路找,

"9p
"8p
"7p
"6p
"5p
"4p
"3p
"2p
"1p


当然,顺序也可以反过来啦!但方法实在不是普通的难看。如果旁边有人,有可能导致一世英名毁于一旦。所以做这件事情的时候,得用比较好看一点的姿势来做。

首先,我先说明,这个方法,是由数字小到大呼叫缓冲区。无法由大到小。呼叫的第一个缓冲区,可以不必由缓冲区 1 开始,可以是其它数字。我个人因脑袋长得比较小,年纪也比较大,所以我习惯从头开始,

"1p

出现的当然毫无疑问地是最后一次。然后,

u.

u undo 的意思,屏幕上缓冲区 1 的数据会消失。而 dot (.) repeat 的意思。效果相当于呼叫下一个缓冲区的数据,所以缓冲区 2 的资料会显示出来。想再看下一个缓冲区,就再打一次 u. 就可以了。

如果无法在数字缓冲区找回数据,只要在还未存档的的情况下,我会将现状另存新档,然后回复原编辑档案的数据,搜寻到数据后,放在具名的缓冲区内,再编辑刚刚另存的新档即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值