LINUX下VI编辑器指令讲解
类别: LINUX教程
使用 vi 如何以简单有条理的方式来重复处理档案中的资料,并在不更动原档案的情况下,将这些数据存放到新档案中?
严格说来,这样的处理作业,应该选择像sed、awk这样的工具,在处理效率上比较好;如果处理需求单纯的话,grep 也足以应付。但那样的选择,通常是在处理流程已经相当成熟,且有必要经常性的重复使用之下才会做出。在突发性且处理模式尚未理清前,使用 vi 是较具弹性的选择。
我以一个整理httpd access_log来作说明。
某日凌晨,我刚好在主机上做测试,当时的网络有点忙,我用 netstat -ct 看了一会儿网络的状况,知道目前 httpd 有几位访客。一时兴起想看看他们来看什么,于是我使用 vi 去看了一下 Apache 的 access_log,意外地发现,同一时间,我的同胞 202.102.141.XX(为保护当事人的隐私起见,编者此处进行过处理) 正在扫描主机的 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.XX,所遗留的拜访纪录全部挪移到档案的最末端。指令如下:
:g/202.102.141.XX/mo$
该行指令其中 g 代表 global,是整个档案的意思。在 :g/ 后面的是要搜寻的字符串,我代入的是 202.102.141.XX,也就是有为青年一号。最后 mo$ 其实是 ex 编辑器的指令,mo 是 move 搬移;$ 则代表最后一行的意思。所以这行指令做的就是,将档案从上到下检查内含有 202.102.141.XX 的每一行,找到了就将该行搬移到档案的最后一行。执行完毕后,光标会停留在最后一行。
这样,我就达到将"有为青年一号"的拜访数据透析出来的目的了。当然,我是可以继续使用相同的手法整理有为青年二、三号,不过我的想法是单独存盘,所以这时还不需要处理。紧接着我要删除无关的数据。
:/202.102.141.XX
因为光标已在最后一行,搜寻会自动跳回第一行重头开始寻找字符串。藉此,我已将光标移动到"有为青年一号"数据的开头位置。光标以上的是我不需要的数据,以下则是打算存档的内容。
接着我将光标往上跳一行(也就是按一下 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. 就可以了。
如果无法在数字缓冲区找回数据,只要在还未存档的情况下,我会将现状另存新档,然后回复原编辑档案的数据,搜寻到数据后,放在具名的缓冲区内,再编辑刚刚另存的新档即可。
严格说来,这样的处理作业,应该选择像sed、awk这样的工具,在处理效率上比较好;如果处理需求单纯的话,grep 也足以应付。但那样的选择,通常是在处理流程已经相当成熟,且有必要经常性的重复使用之下才会做出。在突发性且处理模式尚未理清前,使用 vi 是较具弹性的选择。
我以一个整理httpd access_log来作说明。
某日凌晨,我刚好在主机上做测试,当时的网络有点忙,我用 netstat -ct 看了一会儿网络的状况,知道目前 httpd 有几位访客。一时兴起想看看他们来看什么,于是我使用 vi 去看了一下 Apache 的 access_log,意外地发现,同一时间,我的同胞 202.102.141.XX(为保护当事人的隐私起见,编者此处进行过处理) 正在扫描主机的 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.XX,所遗留的拜访纪录全部挪移到档案的最末端。指令如下:
:g/202.102.141.XX/mo$
该行指令其中 g 代表 global,是整个档案的意思。在 :g/ 后面的是要搜寻的字符串,我代入的是 202.102.141.XX,也就是有为青年一号。最后 mo$ 其实是 ex 编辑器的指令,mo 是 move 搬移;$ 则代表最后一行的意思。所以这行指令做的就是,将档案从上到下检查内含有 202.102.141.XX 的每一行,找到了就将该行搬移到档案的最后一行。执行完毕后,光标会停留在最后一行。
这样,我就达到将"有为青年一号"的拜访数据透析出来的目的了。当然,我是可以继续使用相同的手法整理有为青年二、三号,不过我的想法是单独存盘,所以这时还不需要处理。紧接着我要删除无关的数据。
:/202.102.141.XX
因为光标已在最后一行,搜寻会自动跳回第一行重头开始寻找字符串。藉此,我已将光标移动到"有为青年一号"数据的开头位置。光标以上的是我不需要的数据,以下则是打算存档的内容。
接着我将光标往上跳一行(也就是按一下 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. 就可以了。
如果无法在数字缓冲区找回数据,只要在还未存档的情况下,我会将现状另存新档,然后回复原编辑档案的数据,搜寻到数据后,放在具名的缓冲区内,再编辑刚刚另存的新档即可。
- 上一篇: LINUX下流媒体服务器详细安装,配置
- 下一篇: 菜鸟编译内核(KERNEL2.6.0)
-= 资 源 教 程 =-
文 章 搜 索