Thursday, June 04, 2009
Monday, June 01, 2009
一路向前--写在计算所复试回来的路上
(此文很早就写好了,但一直拖着没法,明天后就要毕业走人了,终于下决心发了)
在北京呆了五天后,坐上了南下的列车,百无聊赖,写下了这篇文章。回想当初,自己在网上狂搜各类计算所,软件所“考经”,并将其打印成册,视若珍宝,很多 次迷茫,忧伤,无助之时,便翻开细细品位,它们给了我很大的动力和宝贵的经验。尤其是那篇如诗般的“轻轻的,我来了计算所”,每每读完后,心若秋水,平静 而充满力量。我的整个复习计划也大致和这位师兄相同。
一、为什么要考中科院
去年的这个时候,大三,我还是一个无工作念头,又无保研希望,无考研目标的三无青年。某日,在qq上收到昔日一位不是很熟的朋友,误以为我是大四的,问我 签哪了,然后我无意的回问了句“你呢?”,得知他已考上中科院信号处理专业的研究生了,得知在那上学既不用交钱,而且每个月又有不少钱发,当时就把我那颗 迷糊的心给触动了。我是农村了,父母年纪也也大了,真的不想再给他们添负担了,现在越来越多的高校都实行奖学金制度,而中科院如此优厚的条件,对我是多么 具有诱惑力啊!当然,同样令我心情澎湃的是中科院的实力。于是,你应该这样问自己,为什么不考中科院呢?
二、备考
大三下期,专业课比较密集。操作系统,编译原理,我们都是这时上的。所以4、5月的主要工作就是,在准备期末考试的同时,强化了对os,cp的学习,为日后的专业课复习打下基础(事实证明,后来省下我不少事)。
暑假,用师兄的话说,是考研的黄金时期。这两个月将为日后的复习打下一个基础,不仅仅是知识层面,也包括你对待考研的心态。这个基础将决定你日后的分数的 档次。当然这期间有人会埋怨说有实习什么的,既然决定考研了,就要一切以考研为重,把它当成你的一项事业那样一心一意的去对待它。20来天的实习期间,我 一边看数学课本,一边做灯哥。后来又买了石崇帧的220篇。还有一本六级词汇,长难句分析,这些构成了我暑假的全部装备。
这个时候,天气很热很热,显然得去占个靠风扇的地方上自习,可以提高效率,省得到处奔波,消磨斗志。实在占不到,就送你两个字“坚持”。这个时期,如果你找到了整天沉浸到自习中的乐趣时,你就已经找到了感觉了。
如果,每隔2-3周,你会出现睡眠问题,或不想读书之类的状况,恭喜你,你已经入门了(注:本文大多数观点仅适合那些学习较为刻苦的孩子,至于那些高级别 的人物不在此列,以免误导)。有人将此时称之为“考研综合症”。其实,这个问题一直伴随着我整个考研过程中,乃至考完研后一段时间内--非常非常的痛苦。 我当时尝试过很多解决办法,较凑效的是:(1)放松下,跑跑步,运动;(2)吃补脑安神丸;开始这两种方法都挺管用的。但到后来效果渐渐削弱,也许我天性 就是一个太过于心急的人吧,不懂得如何去放松。最狠的第三招,此招过于毒辣,我只用过一次--既然不想睡,就撑下去!直到你撑不下去为止。此招也是网上看 到的,发明此招的牛人说撑了两天两夜,后来到床就睡。我当时撑到半夜3点,然后果然睡的天昏地暗。第三天也是。
睡眠不好,很容易影响第二天的学习效率和心情。这也是我认为考研中最大的困难。所以大家注意“劳逸结合,事半功倍”这句话。效率不高时不要死撑,注意调节。
三、强化
当我单词背完3,4遍后,灯哥啃完一遍后,220篇做完后,第一阶段的复习也宣告结束了。这个时间最好是控制在9月以内吧。我的计划执行力不够,每一阶段 总比《轻轻的我来了》一文中的要缓10天,到考研前一两天,总算尝到了苦果。我们应该记住,计划往往会受到不可预知的因素的影响。所以我们应该慷慨的为这 些不可预知因素留有生存空间。比如,你的目标是370分,那么你就要计划你自己打400分以上;不要计划在考试前恰好完成所有复习,那是非常错误的,你应 该至少提前十天。
九月份开始看政治,每天中午睡前,醒后看红宝书1-2个小时,即10页。慢吞吞的看到了10月份,总算看完,但不知所云,和没看感觉没什么两样。于是,面 对政治惶惶不可终日,病急乱吃药,后来又看了应试精华,核心考案,什么的。走了很多弯路。其实,我觉得,应付政治正道耐心把红宝书多看几遍,一遍不行,再 看,还不行,再看一遍,依次循环,直至滚瓜烂熟,同时可买本习题集做做。至于买哪本,我只能告诉你不要买人大名师1800题,因为我只用过那个,封面序言 里吹牛用了的都能拿80分以上,其实里面都是些过时的题。这些习题集都是你抄我,我抄你的,买本大众化的就行了。切忌不要想我一样,在自己不熟悉的领域还 试图标新立异。有条件的上个班还是挺值得的(虽然我没有上过任何考研班,但也听过很多政治考研班的录音)。
关于政治,早期多做选择题,后期多背背,把红宝书弄熟,就可以不变应万变了。
英语,说实话,我的220篇一直拖到10月20才做完,其余还是背单词,不能停。
数学,灯哥做完第二遍,但感觉比第一遍难做,因为第一遍是先看一章,做一章的题。而第二遍,好多东西又都忘了。
专业课,看了看数据结构课本,有不太容易懂的地方,可去看严蔚敏老师的视频,讲的很不错。
四、冲刺
前面两轮过后,离考试的时间也越来越近了,近到你渐渐可以感受的它的气息。那时候,总觉得自己其实什么也没做,心里也渐渐开始急躁起来,越来越容易受环境 的影响。幸好,在我考研过程中遇到了好几个同伴,其中有几个也是计算机专业,大家整天在图书馆的固定地方上自习。考研除了坚持,计划,自我调整外,还有一 点最重要了,那就是与别人沟通。那样你可以消除你内心的压力,恐惧,迷茫,你可以获得更多信息,大家一起相互鼓励支持。这会你取得事半功倍的效果。真的, 很庆幸,也很感谢老天爷让我遇到我的他们。没有他们,我不知道我会不会有现在这样的结果。
前面说道,由于我总比别人要慢10天,在这个时候终于尝到了苦果。时间进入12月,灯哥第三遍,要做完明显不太可能了,只好挑重点难点逐个攻破,英语就做 了两套真题,其余时间全部花在政治和专业课上了。更惨的是,直到考试前两天,我还没有做过操作系统的题目,仅仅是只看了书而已,一方面因为这门课没有好的 辅导材料,另一方面是计划没有把握好。
天越来越冷,后来下雪,好像从下的那天起到过年回家,那场雪就再也没有融过--后来被称为百年不遇的冰雪灾害,有幸成了灾民。小说中大战前总会有飞沙走 石,这也是预示那场战斗渐渐来临吧。那几天,清晨,独自一人,撑着伞,踏在那平坦的白色雪地,一步一个脚印,听着The Mass、神圣的战争和征服天堂,走在去图书馆的路上,眼泪禁不住往下流,我问自己“为了什么”,答“为了自己的理想”,“多少个日日夜夜,我已经这样走 过,这条路,我会一直向前,即使是失败,也无怨无悔,因为我已经尽力了”。
五、考试
终于到了,那 三天不知道是不是天天坐在图书馆上自己太久了,腰一坐下没两分钟就很痛,只好买了膏药贴上。那两天,天空飘着似雪非雪,似冰非冰的东西,地上到处积满冰 雪,大家都小心翼翼的挪动着脚步,但还是有很多人滑倒。坐在考场,前面的人一直在抖,正想提醒他,后面的人敲了下我的背,叫我别抖,原来我也在抖。有人带 了很多东西,热水袋,热水瓶,毛鞋,垫子,跟搬家似的。最要命的是脚,虽然我穿了三双袜子,还有最厚的那双皮鞋,还是跟一直放在冰块上似的,很难受。 出了考场,寒风一吹,感觉神经都在颤栗,你都不知道身上还有哪一部分是受你控制的。第一天下来,被冻着了,晚上准备去上自习,但头晕的很,想撑一会,却发 现连呼吸都困难起来,只好去了医院,打了瓶点滴,本来还想把专业课,数学剩下的任务完成的,现在成了泡影。回来后,脑子里很乱,由于开始的计划执行落后, 我对专业课和数学没有把握,更要命的是我对我目前这样的状态,真不知道明天能不能撑下去。快绝望了,给妈打了个电话,我说我可能考不上。妈妈听了,妈说没 考上,也没关系,凭我的能力,找个工作也不是难事,她没有给我压力,她更关心我的身体。躺在床上,过了几十分钟,又接到了妈的电话,她很激动的和我说:“ 儿子,我前几天作了个梦,梦见遇到了一个神仙...他告诉我,你考哪里都能考上”。霎时,我的眼泪汹涌而出,心里顿觉滚烫滚烫的。我在墙上写下了妈对我说 的话,又坐在了台灯前...
第二天的数学题目出的很怪,也因为天太冷,感冒的原因,思维转动很慢,做起来很没感觉,有的题简单的令人难以置信,以至于用初中知识或两三句话就可答完。 而最后一题第一问的证明确怎么算都算不对,我跟老师示意想上厕所,借机在走廊上换了口气。专业课还算顺利,基本上都知道怎么做,特别是操作系统,昨天晚上 看得,有二十多分,不过也很遗憾,如果再多看一点的话,恐怕更高。提前半个小时做完,心里那根绷紧的弦总算松了下来。当铃声响起,随着人流走在下楼的楼梯 上,我意犹未尽的对自己说“就这样结束了吗?”,这段日子就这样过去了,还真有点不舍。
六、总结
考研=决心+计划+坚持+自我调整+多与人沟通
希望这一点点经验对你有用,加油!
Tuesday, May 26, 2009
Thursday, May 14, 2009
(转)gdb –annotate=
转自:http://blog.163.com/zhang7410@126/blog/static/233564612008338548800/
Emacs中使用gdb命令调试,然后用
gdb –annotate=0 myprog.exe 启动gdb进入gud-mode ,
不同的annotate 的值不代表不同的模式
annotate = 0是最基本的模式和在命令行使用gdb完全一样。
annotate = 1是单步调试模式,出现上下两个窗口,上面是gdb运行的buffer,下面是你代码的buffer,会在代码 buffer中,同步指示当前运行的语句的位置。
annotate = 3是信息最完整的模式,会进入一个多窗口界面同时显示6个窗口分别是gdb-buffer, locals-buffer(局部 变量),source-buffer,inferor I/Obuffer(正在调试程序的IO),stack-buffer,breakpoint-buffer.
无论上面的那种情况,都出现了一个现象:程序的输出不能显示,只有在程序退出的时候才显示出来。这样是非常不方便的。
GUD/GDB mode:
M-x gdb --annotate=3 test ;;进入gdb
如果没有进入graphical mode可以 M-x gdba 然后输入你要debug的file
C-x : set breakpoint ;;可以直接点击旁边的fringe set/clear 断点
C-c C-l : clear breakpoint
C-c C-s : step(step one line code but stop in function)
C-c C-n : next(step one line code but stepping across function)
C-c C-i : stepi(Execute a single machine instruction)
C-c C-r : continue(感觉还是直接按go按钮吧)
C-c C-d : Delete the breakpoint(s) on the current source line
其他:
1. 如果更改了gdb的window 可以用: M-x gdb-restore-windows 恢复
在breakpoint buffer上:
2 Return : gdb-goto-breakpoint (即转到source对应的行)
3.D : gdb-delete-breakpoint
4.Space : Enable/disable the current breakpoint (`gdb-toggle-breakpoint')
5: 可以将鼠标放到一个variable上, 然后点击toolbar上的watch就可以watch a expression了
这是varibale显示在 speedbar中:
return: To expand or contract a complex data type
D : To delete a complex watch expression
space : To edit a variable with a simple data type
6: C-x C-a C-l : refresh a bufferSunday, May 10, 2009
(转)sed命令
sed 编辑器是 Linux 系统管理员的工具包中最有用的资产之一,
因此,有必要彻底地了解其应用
Linux 操作系统最大的一个好处是它带有各种各样的实用工具。存在如此之多不同的实用工具,几乎不可能知道并了解所有这些工具。可以简化关键情况下操作的一个实用工具是 sed。它是任何管理员的工具包中最强大的工具之一,并且可以证明它自己在关键情况下非常有价值。
sed 实用工具是一个“编辑器”,但它与其它大多数编辑器不同。除了不面向屏幕之外,它还是非交互式的。这意味着您必须将要对数据执行的命令插入到命令行或要处理的脚本中。当显示它时,请忘记您在使用 Microsoft Word 或其它大多数编辑器时拥有的交互式编辑文件功能。sed 在一个文件(或文件集)中非交互式、并且不加询问地接收一系列的命令并执行它们。因而,它流经文本就缤 骶 饕谎 蚨?sed 恰当地代表了流编辑器。它可以用来将所有出现的 "Mr. Smyth" 修改为 "Mr. Smith",或将 "tiger cub" 修改为 "wolf cub"。流编辑器非常适合于执行重复的编辑,这种重复编辑如果由人工完成将花费大量的时间。其参数可能和一次性使用一个简单的操作所需的参数一样有限,或者和一个具有成千上万行要进行编辑修改的脚本文件一样复杂。sed 是 Linux 和 UNIX 工具箱中最有用的工具之一,且使用的参数非常少。
sed 的工作方式
sed 实用工具按顺序逐行将文件读入到内存中。然后,它执行为该行指定的所有操作,并在完成请求的修改之后将该行放回到内存中,以将其转储至终端。完成了这一行 上的所有操作之后,它读取文件的下一行,然后重复该过程直到它完成该文件。如同前面所提到的,默认输出是将每一行的内容输出到屏幕上。在这里,开始涉及到 两个重要的因素—首先,输出可以被重定向到另一文件中,以保存变化;第二,源文件(默认地)保持不被修改。sed 默认读取整个文件并对其中的每一行进行修改。不过,可以按需要将操作限制在指定的行上。
该实用工具的语法为:
sed [options] '{command}' [filename]
在这篇文章中,我们将浏览最常用的命令和选项,并演示它们如何工作,以及它们适于在何处使用。
替换命令
sed 实用工具以及其它任何类似的编辑器的最常用的命令之一是用一个值替换另一个值。用来实现这一目的的操作的命令部分语法是:
's/{old value}/{new value}/'
因而,下面演示了如何非常简单地将 "tiger" 修改为 "wolf":
$ echo The tiger cubs will meet on Tuesday after school | sed
's/tiger/wolf/'
The wolf cubs will meet on Tuesday after school
$
注意如果输入是源自之前的命令输出,则不需要指定文件名—同样的原则也适用于 awk、sort 和其它大多数 Linux\UNIX 命令行实用工具程序。
多次修改
如果需要对同一文件或行作多次修改,可以有三种方法来实现它。第一种是使用 "-e" 选项,它通知程序使用了多条编辑命令。例如:
$ echo The tiger cubs will meet on Tuesday after school | sed -e '
s/tiger/wolf/' -e 's/after/before/'
The wolf cubs will meet on Tuesday before school
$
这是实现它的非常复杂的方法,因此 "-e" 选项不常被大范围使用。更好的方法是用分号来分隔命令:
$ echo The tiger cubs will meet on Tuesday after school | sed '
s/tiger/wolf/; s/after/before/'
The wolf cubs will meet on Tuesday before school
$
注意分号必须是紧跟斜线之后的下一个字符。如果两者之间有一个空格,操作将不能成功完成,并返回一条错误消息。这两种方法都很好,但许多管理员更喜欢另一种方法。要注意的一个关键问题是,两个撇号 (' ') 之间的全部内容都被解释为 sed 命令。直到您输入了第二个撇号,读入这些命令的 shell 程序才会认为您完成了输入。这意味着可以在多行上输入命令—同时 Linux 将提示符从 PS1 变为一个延续提示符(通常为 ">")—直到输入了第二个撇号。一旦输入了第二个撇号,并且按下了 Enter 键,则处理就进行并产生相同的结果,如下所示:
$ echo The tiger cubs will meet on Tuesday after school | sed '
> s/tiger/wolf/
> s/after/before/'
The wolf cubs will meet on Tuesday before school
$
全局修改
让我们开始一次看似简单的编辑。假定在要修改的消息中出现了多次要修改的项目。默认方式下,结果可能和预期的有所不同,如下所示:
$ echo The tiger cubs will meet this Tuesday at the same time
as the meeting last Tuesday | sed 's/Tuesday/Thursday/'
The tiger cubs will meet this Thursday at the same time
as the meeting last Tuesday
$
与将出现的每个 "Tuesday" 修改为 "Thursday" 相反,sed 编辑器在找到一个要修改的项目并作了修改之后继续处理下一行,而不读整行。sed 命令功能大体上类似于替换命令,这意味着它们都处理每一行中出现的第一个选定序列。为了替换出现的每一个项目,在同一行中出现多个要替换的项目的情况下,您必须指定在全局进行该操作:
$ echo The tiger cubs will meet this Tuesday at the same time
as the meeting last Tuesday | sed 's/Tuesday/Thursday/g'
The tiger cubs will meet this Thursday at the same time
as the meeting last Thursday
$
请记住不管您要查找的序列是否仅包含一个字符或词组,这种对全局化的要求都是必需的。
sed 还可以用来修改记录字段分隔符。例如,以下命令将把所有的 tab 修改为空格:
sed 's// /g'
其中,第一组斜线之间的项目是一个 tab,而第二组斜线之间的项目是一个空格。作为一条通用的规则,sed 可以用来将任意的可打印字符修改为任意其它的可打印字符。如果您想将不可打印字符修改为可打印字符—例如,铃铛修改为单词 "bell"—sed 不是适于完成这项工作的工具(但 tr 是)。
有时,您不想修改在一个文件中出现的所有指定项目。有时,您只想在满足某些条件时才作修改—例如,在与其它一些数据匹配之后才作修改。为了说明这一点,请考虑以下文本文件:
$ cat sample_one
one 1
two 1
three 1
one 1
two 1
two 1
three 1
$
假定希望用 "2" 来替换 "1",但仅在单词 "two" 之后才作替换,而不是每一行的所有位置。通过指定在给出替换命令之前必须存在一次匹配,可以实现这一点:
$ sed '/two/ s/1/2/' sample_one
one 1
two 2
three 1
one 1
two 2
two 2
three 1
$
现在,使其更加准确:
$ sed '
> /two/ s/1/2/
> /three/ s/1/3/' sample_one
one 1
two 2
three 3
one 1
two 2
two 2
three 3
$
请再次记住唯一改变了的是显示。如果您查看源文件,您将发现它始终保持不变。您必须将输出保存至另一个文件,以实现永久保存。值得重复的是,不对源文件作 修改实际是祸中有福—它让您能够对文件进行试验而不会造成任何实际的损害,直到让正确命令以您预期和希望的方式进行工作。
以下命令将修改后的输出保存至一个新的文件:
$ sed '
> /two/ s/1/2/
> /three/ s/1/3/' sample_one > sample_two
该输出文件将所有修改合并在其中,并且这些修改通常将在屏幕上显示。现在可以用 head、cat 或任意其它类似的实用工具来进行查看。
脚本文件
sed 工具允许您创建一个脚本文件,其中包含从该文件而不是在命令行进行处理的命令,并且 sed 工具通过 "-f" 选项来引用。通过创建一个脚本文件,您能够一次又一次地重复运行相同的操作,并指定比每次希望从命令行进行处理的操作详细得多的操作。
考虑以下脚本文件:
$ cat sedlist
/two/ s/1/2/
/three/ s/1/3/
$
现在可以在数据文件上使用脚本文件,获得和我们之前看到的相同的结果:
$ sed -f sedlist sample_one
one 1
two 2
three 3
one 1
two 2
two 2
three 3
$
注意当调用 "-f" 选项时,在源文件内或命令行中不使用撇号。脚本文件,也称为源文件,对于想重复多次的操作和从命令行运行可能出错的复杂命令很有价值。编辑源文件并修改一个字符比在命令行中重新输入一条多行的项目要容易得多。
限制行
编辑器默认查看输入到流编辑器中的每一行,且默认在输入到流编辑器中的每一行上进行编辑。这可以通过在发出命令之前指定约束条件来进行修改。例如,只在此示例文件的输出的第 5 和第 6 行中用 "2" 来替换 "1",命令将为:
$ sed '5,6 s/1/2/' sample_one
one 1
two 1
three 1
one 1
two 2
two 2
three 1
$
在这种情况下,因为要修改的行是专门指定的,所以不需要替换命令。因此,您可以灵活地根据匹配准则(可以是行号或一种匹配模式)来选择要修改哪些行(从根本上限制修改)。
禁止显示
sed 默认将来自源文件的每一行显示到屏幕上(或重定向到一个文件中),而无论该行是否受到编辑操作的影响,"-n" 参数覆盖了这一操作。"-n" 覆盖了所有的显示,并且不显示任何一行,而无论它们是否被编辑操作修改。例如:
$ sed -n -f sedlist sample_one
$
$ sed -n -f sedlist sample_one > sample_two
$ cat sample_two
$
在第一个示例中,屏幕上不显示任何东西。在第二个示例中,不修改任何东西,因此不将任何东西写到新的文件中—它最后是空的。这不是否定了编辑的全部目的吗?为什么这是有用的?它是有用的仅因为 "-n" 选项能够被一条显示命令 (-p) 覆盖。为了说明这一点,假定现在像下面这样对脚本文件进行了修改:
$ cat sedlist
/two/ s/1/2/p
/three/ s/1/3/p
$
然后下面是运行它的结果:
$ sed -n -f sedlist sample_one
two 2
three 3
two 2
two 2
three 3
$
保持不变的行全部不被显示。只有受到编辑操作影响的行被显示了。在这种方式下,可以仅取出这些行,进行修改,然后把它们放到一个单独的文件中:
$ sed -n -f sedlist sample_one > sample_two
$
$ cat sample_two
two 2
three 3
two 2
two 2
three 3
$
利用它的另一种方法是只显示一定数量的行。例如,只显示 2-6 行,同时不做其它的编辑修改:
$ sed -n '2,6p' sample_one
two 1
three 1
one 1
two 1
two 1
$
其它所有的行被忽略,只有 2-6 行作为输出显示。这是一项出色的功能,其它任何工具都不能容易地实现。Head 将显示一个文件的顶部,而 tail 将显示一个文件的底部,但 sed 允许从任意位置取出想要的任意内容。
删除行
用一个值替换另一个值远非流编辑器可以执行的唯一功能。它还具有许多的潜在功能,在我看来第二种最常用的功能是删除。删除与替换的工作方式相同,只是它删除指定的行(如果您想要删除一个单词而不是一行,不要考虑删除,而应考虑用空的内容来替换它—s/cat//)。
该命令的语法是:
'{what to find} d'
从 sample_one 文件中删除包含 "two" 的所有行:
$ sed '/two/ d' sample_one
one 1
three 1
one 1
three 1
$
从显示屏中删除前三行,而不管它们的内容是什么:
$ sed '1,3 d' sample_one
one 1
two 1
two 1
three 1
$
只显示剩下的行,前三行不在显示屏中出现。对于流编辑器,一般当它们涉及到全局表达式时,特别是应用于删除操作时,有几点要记住:
上三角号 (^) 表示一行的开始,因此,如果 "two" 是该行的头三个字符,则
sed '/^two/ d' sample_one
将只删除该行。
美元符号 ($) 代表文件的结尾,或一行的结尾,因此,如果 "two" 是该行的最后三个字符,则
sed '/two$/ d' sample_one
将只删除该行。
将这两者结合在一起的结果:
sed '/^$/ d' {filename}
删除文件中的所有空白行。例如,以下命令将 "1" 替换为 "2",以及将 "1" 替换为 "3",并删除文件中所有尾随的空行:
$ sed '/two/ s/1/2/; /three/ s/1/3/; /^$/ d' sample_one
one 1
two 1
three 1
one 1
two 2
two 2
three 1
$
其通常的用途是删除一个标题。以下命令将删除文件中所有的行,从第一行直到第一个空行:
sed '1,/^$/ d' {filename}
添加和插入文本
可以结合使用 sed 和 "a" 选项将文本添加到一个文件的末尾。实现方法如下:
$ sed '$a\
> This is where we stop\
> the test' sample_one
one 1
two 1
three 1
one 1
two 1
two 1
three 1
This is where we stop
the test
$
在该命令中,美元符号 ($) 表示文本将被添加到文件的末尾。反斜线 (\) 是必需的,它表示将插入一个回车符。如果它们被遗漏了,则将导致一个错误,显示该命令是错乱的;在任何要输入回车的地方您必须使用反斜线。
要将这些行添加到第 4 和第 5 个位置而不是末尾,则命令变为:
$ sed '3a\
> This is where we stop\
> the test' sample_one
one 1
two 1
three 1
This is where we stop
the test
one 1
two 1
two 1
three 1
$
这将文本添加到第 3 行之后。和几乎所有的编辑器一样,您可以选择插入而不是添加(如果您希望这样的话)。这两者的区别是添加跟在指定的行之后,而插入从指定的行开始。当用插入来代替添加时,只需用 "i" 来代替 "a",如下所示:
$ sed '3i\
> This is where we stop\
> the test' sample_one
one 1
two 1
This is where we stop
the test
three 1
one 1
two 1
two 1
three 1
$
新的文本出现在输出的中间位置,而处理通常在指定的操作执行以后继续进行。
读写文件
重定向输出的功能已经演示过了,但需要指出的是,在编辑命令运行期间可以同步地读入和写出文件。例如,执行替换,并将 1-3 行写到名称为 sample_three 的文件中:
$ sed '
> /two/ s/1/2/
> /three/ s/1/3/
> 1,3 w sample_three' sample_one
one 1
two 2
three 3
one 1
two 2
two 2
three 3
$
$ cat sample_three
one 1
two 2
three 3
$
由于为 w (write) 命令指定了 "1,3",所以只有指定的行被写到了新文件中。无论被写的是哪些行,所有的行都在默认输出中显示。
修改命令
除了替换项目之外,还可以将行从一个值修改为另一个值。要记住的是,替换是对字符逐个进行,而修改功能与删除类似,它影响整行:
$ sed '/two/ c\
> We are no longer using two' sample_one
one 1
We are no longer using two
three 1
one 1
We are no longer using two
We are no longer using two
three 1
$
修改命令与替换的工作方式很相似,但在范围上要更大些—将一个项目完全替换为另一个项目,而无论字符内容或上下文。夸张一点讲,当使用替换时,只有字符 "1" 被字符 "2" 替换,而当使用修改时,原来的整行将被修改。在两种情况下,要寻找的匹配条件都仅为 "two"。
修改全部但……
对于大多数 sed 命令,详细说明各种功能要进行何种修改。利用感叹号,可以在除指定位置之外的任何地方执行修改—与默认的操作完全相反。
例如,要删除包含单词 "two" 的所有行,操作为:
$ sed '/two/ d' sample_one
one 1
three 1
one 1
three 1
$
而要删除除包含单词 "two" 的行之外的所有行,则语法变为:
$ sed '/two/ !d' sample_one
two 1
two 1
two 1
$
如果您有一个文件包含一系列项目,并且想对文件中的每个项目执行一个操作,那么首先对那些项目进行一次智能扫描并考虑将要做什么是很重要的。为了使事情变得更简单,您可以将 sed 与任意迭代例程(for、while、until)结合来实现这一目的。
比如说,假定您有一个名为 "animals" 的文件,其中包含以下项目:
pig
horse
elephant
cow
dog
cat
您希望运行以下例程:
#mcd.ksh
for I in $*
do
echo Old McDonald had a $I
echo E-I, E-I-O
done
结果将为,每一行都显示在 "Old McDonald has a" 的末尾。虽然对于这些项目的大部分这是正确的,但对于 "elephant" 项目,它有语法错误,因为结果应当为 "an elephant" 而不是 "a elephant"。利用 sed,您可以在来自 shell 文件的输出中检查这种语法错误,并通过首先创建一个命令文件来即时地更正它们:
#sublist
/ a a/ s/ a / an /
/ a e/ s/ a / an /
/a i/ s / a / an /
/a o/ s/ a / an /
/a u/ s/ a / an /
然后执行以下过程:
$ sh mcd.ksh 'cat animals' | sed -f sublist
现在,在运行了 mcd 脚本之后,sed 将在输出中搜索单个字母 a (空格,"a",空格)之后紧跟了一个元音的任意位置。如果这种位置存在,它将把该序列修改为空格,"an",空格。这样就使问题更正后才显示在屏幕上,并确保各处的编辑人员在晚上可以更容易地入睡。结果是:
Old McDonald had a pig
E-I, E-I-O
Old McDonald had a horse
E-I, E-I-O
Old McDonald had an elephant
E-I, E-I-O
Old McDonald had a cow
E-I, E-I-O
Old McDonald had a dog
E-I, E-I-O
Old McDonald had a cat
E-I, E-I-O
提前退出
sed 默认读取整个文件,并只在到达末尾时才停止。不过,您可以使用退出命令提前停止处理。只能指定一条退出命令,而处理将一直持续直到满足调用退出命令的条件。
例如,仅在文件的前五行上执行替换,然后退出:
$ sed '
> /two/ s/1/2/
> /three/ s/1/3/
> 5q' sample_one
one 1
two 2
three 3
one 1
two 2
$
在退出命令之前的项目可以是一个行号(如上所示),或者一条查找/匹配命令:
$ sed '
> /two/ s/1/2/
> /three/ s/1/3/
> /three/q' sample_one
one 1
two 2
three 3
$
您还可以使用退出命令来查看超过一定标准数目的行,并增加比 head 中的功能更强的功能。例如,head 命令允许您指定您想要查看一个文件的前多少行—默认数为 10,但可以使用从 1 到 99 的任意一个数字。如果您想查看一个文件的前 110 行,您用 head 不能实现这一目的,但用 sed 可以:
sed 110q filename
处理问题
当使用 sed 时,要记住的重要事项是它的工作方式。它的工作方式是:读入一行,在该行上执行它已知要执行的所有任务,然后继续处理下一行。每一行都受给定的每一个编辑命令的影响。
如果您的操作顺序没有十分彻底地考虑清楚,那么这可能会很麻烦。例如,假定您需要将所有的 "two" 项目修改为 "three",然后将所有的 "three" 修改为 "four":
$ sed '
> /two/ s/two/three/
> /three/ s/three/four/' sample_one
one 1
four 1
four 1
one 1
four 1
four 1
four 1
$
最初读取的 "two" 被修改为 "three"。然后它满足为下一次编辑建立的准则,从而变为 "four"。最终的结果不是想要的结果—现在除了 "four" 没有别的项目了,而本来应该有 "three" 和 "four"。
当执行这种操作时,您必须非常用心地注意指定操作的方式,并按某种顺序来安排它们,使得操作之间不会互相影响。例如:
$ sed '
> /three/ s/three/four/
> /two/ s/two/three/' sample_one
one 1
three 1
four 1
one 1
three 1
three 1
four 1
$
这非常有效,因为 "three" 值在 "two" 变成 "three" 之前得到修改。
标签和注释
可以在 sed 脚本文件中放置标签,这样一旦文件变得庞大,可以更容易地说明正在发生的事情。存在各种各样与这些标签相关的命令,它们包括:
接下来的步骤
访问并收藏 Linux 技术中心
阅读 Dale Dougherty 和 Arnold Robbins 的著作 sed & awk, 2nd Edition (O'Reilly & Associates 出版社)。
: 冒号表示一个标签名称。例如:
:HERE
以冒号开始的标签可以由 "b" 和 "t" 命令处理。
b {label} 充当 "goto" 语句的作用,将处理发送至前面有一个冒号的标签。例如,
b HERE
将处理发送给行
:HERE
如果紧跟 b 之后没有指定任何标签,则处理转至脚本文件的末尾。
t {label} 只要自上次输入行或执行一次 "t" 命令以来进行了替换操作,就转至该标签。和 "b" 一样,如果没有给定标签名,则处理转至脚本文件的末尾。
# 符号作为一行的第一个字符将使整行被当作注释处理。注释行与标签不同,不能使用 b 或 t 命令来转到注释行上。
进一步的研究
sed 实用工具是 Linux 管理员拥有的最强大和灵活的工具之一。虽然本文覆盖了许多基础知识,但对于这一具有丰富功能的工具仅是蜻蜓点水。关于更多信息,最好的来源之一是 Dale Dougherty 和 Arnold Robbins 的著作 sed & awk,现在从 O'Reilly & Associates 出版社推出了其第二版(参加“接下来的步骤”)。该出版社还推出了一本可以随身携带的袖珍参考
‘s / \ . $ / / g’ 删除以句点结尾行
‘-e /abcd/d’ 删除包含a b c d的行
‘s / [ ] [ ] [ ] * / [ ] / g’ 删除一个以上空格,用一个空格代替
‘s / ^ [ ] [ ] * / / g’ 删除行首空格
‘s / \ . [ ] [ ] * / [ ] / g’ 删除句点后跟两个或更多空格,代之以一个空格
‘/ ^ $ / d’ 删除空行
‘s / ^ . / / g’ 删除第一个字符
‘s /CO L \ ( . . . \ ) / / g’ 删除紧跟C O L的后三个字母
‘s / ^ \ / / / g’ 从路径中删除第一个\
‘s / [ ] / [ ] / / g’ 删除所有空格并用t a b键替代
‘S / ^ [ ] / / g’ 删除行首所有t a b键
‘s / [ ] * / / g’ 删除所有t a b键
(转)awk用法总结
awk中的正则表达式
awk '/101/,/105/' file 打印匹配101和105之间的行
(转)awk使用手册
什么是awk?
你可能对UNIX比较熟悉,但你可能对awk很陌生,这一点也不奇怪,的确,与其优秀的功能相比,awk还远没达到它应有的知名度。awk是什么?与其它大多数UNIX命令不同的是,从名字上看,我们不可能知道awk的功能:它既不是具有独立意义的英文单词,也不是几个相关单词的缩写。事实上,awk是三个人名的缩写,他们是:Aho、(Peter)Weinberg和 (Brain)Kernighan。正是这三个人创造了awk---一个优秀的样式扫描与处理工具。
AWK的功能是什么?与sed和 grep很相似,awk是一种样式扫描与处理工具。但其功能却大大强于sed和grep。awk提供了极其强大的功能:它几乎可以完成grep和sed所能完成的全部工作,同时,它还可以可以进行样式装入、流控制、数学运算符、进程控制语句甚至于内置的变量和函数。它具备了一个完整的语言所应具有的几乎所有精美特性。实际上,awk的确拥有自己的语言:awk程序设计语言,awk的三位创建者已将它正式定义为:样式扫描和处理语言。
为什么使用awk?
即使如此,你也许仍然会问,我为什么要使用awk?
使用awk的第一个理由是基于文本的样式扫描和处理是我们经常做的工作,awk所做的工作有些象数据库,但与数据库不同的是,它处理的是文本文件,这些文件没有专门的存储格式,普通的人们就能编辑、阅读、理解和处理它们。而数据库文件往往具有特殊的存储格式,这使得它们必须用数据库处理程序来处理它们。既然这种类似于数据库的处理工作我们经常会遇到,我们就应当找到处理它们的简便易行的方法,UNIX有很多这方面的工具,例如sed 、grep、sort以及find等等,awk是其中十分优秀的一种。
使用awk的第二个理由是awk是一个简单的工具,当然这是相对于其强大的功能来说的。的确,UNIX有许多优秀的工具,例如UNIX天然的开发工具C语言及其延续C++就非常的优秀。但相对于它们来说,awk完成同样的功能要方便和简捷得多。这首先是因为awk提供了适应多种需要的解决方案:从解决简单问题的awk命令行到复杂而精巧的awk程序设计语言,这样做的好处是,你可以不必用复杂的方法去解决本来很简单的问题。例如,你可以用一个命令行解决简单的问题,而C不行,即使一个再简单的程序,C语言也必须经过编写、编译的全过程。其次,awk本身是解释执行的,这就使得awk程序不必经过编译的过程,同时,这也使得它与shell script程序能够很好的契合。最后,awk本身较C语言简单,虽然awk吸收了C语言很多优秀的成分,熟悉C语言会对学习awk有很大的帮助,但 awk本身不须要会使用C语言——一种功能强大但需要大量时间学习才能掌握其技巧的开发工具。
使用awk的第三个理由是awk是一个容易获得的工具。与C和C++语言不同,awk只有一个文件(/bin/awk),而且几乎每个版本的UNIX都提供各自版本的awk,你完全不必费心去想如何获得awk。但C语言却不是这样,虽然C语言是UNIX天然的开发工具,但这个开发工具却是单独发行的,换言之,你必须为你的UNIX版本的C语言开发工具单独付费(当然使用D版者除外),获得并安装它,然后你才可以使用它。
基于以上理由,再加上awk强大的功能,我们有理由说,如果你要处理与文本样式扫描相关的工作,awk应该是你的第一选择。在这里有一个可遵循的一般原则:如果你用普通的shell工具或shell script有困难的话,试试awk,如果awk仍不能解决问题,则便用C语言,如果C语言仍然失败,则移至C++。
awk的调用方式
前面曾经说过,awk提供了适应多种需要的不同解决方案,它们是:
一、 awk命令行,你可以象使用普通UNIX命令一样使用awk,在命令行中你也可以使用awk程序设计语言,虽然awk支持多行的录入,但是录入长长的命令行并保证其正确无误却是一件令人头疼的事,因此,这种方法一般只用于解决简单的问题。当然,你也可以在shell script程序中引用awk命令行甚至awk程序脚本。
二、使用-f选项调用awk程序。awk允许将一段awk程序写入一个文本文件,然后在awk命令行中用-f选项调用并执行这段程序。具体的方法我们将在后面的awk语法中讲到。
三、利用命令解释器调用awk程序:利用UNIX支持的命令解释器功能,我们可以将一段awk程序写入文本文件,然后在它的第一行加上:
#!/bin/awk -f
并赋予这个文本文件以执行的权限。这样做之后,你就可以在命令行中用类似于下面这样的方式调用并执行这段awk程序了。
$awk脚本文本名 待处理文件
awk的语法:
与其它UNIX命令一样,awk拥有自己的语法:
awk [ -F re] [parameter...] ['prog'] [-f progfile][in_file...]
参数说明:
-F re:允许awk更改其字段分隔符。
parameter: 该参数帮助为不同的变量赋值。
'prog': awk的程序语句段。这个语句段必须用单拓号:'和'括起,以防被shell解释。这个程序语句段的标准形式为:
'pattern {action}'
其中pattern参数可以是egrep正则表达式中的任何一个,它可以使用语法/re/再加上一些样式匹配技巧构成。与sed类似,你也可以使用","分开两样式以选择某个范围。关于匹配的细节,你可以参考附录,如果仍不懂的话,找本UNIX书学学grep和sed(本人是在学习ed时掌握匹配技术的)。 action参数总是被大括号包围,它由一系统awk语句组成,各语句之间用";"分隔。awk解释它们,并在pattern给定的样式匹配的记录上执行其操作。与shell类似,你也可以使用“#”作为注释符,它使“#”到行尾的内容成为注释,在解释执行时,它们将被忽略。你可以省略pattern和 action之一,但不能两者同时省略,当省略pattern时没有样式匹配,表示对所有行(记录)均执行操作,省略action时执行缺省的操作——在标准输出上显示。
-f progfile:允许awk调用并执行progfile指定有程序文件。progfile是一个文本文件,他必须符合awk的语法。
in_file:awk的输入文件,awk允许对多个输入文件进行处理。值得注意的是awk不修改输入文件。如果未指定输入文件,awk将接受标准输入,并将结果显示在标准输出上。awk支持输入输出重定向。
awk的记录、字段与内置变量:
前面说过,awk处理的工作与数据库的处理方式有相同之处,其相同处之一就是awk支持对记录和字段的处理,其中对字段的处理是grep和sed不能实现的,这也是awk优于二者的原因之一。在awk中,缺省的情况下总是将文本文件中的一行视为一个记录,而将一行中的某一部分作为记录中的一个字段。为了操作这些不同的字段,awk借用shell的方法,用$1,$2,$3...这样的方式来顺序地表示行(记录)中的不同字段。特殊地,awk用$0表示整个行(记录)。不同的字段之间是用称作分隔符的字符分隔开的。系统默认的分隔符是空格。awk允许在命令行中用-F re的形式来改变这个分隔符。事实上,awk用一个内置的变量FS来记忆这个分隔符。awk中有好几个这样的内置变量,例如,记录分隔符变量RS、当前工作的记录数NR等等,本文后面的附表列出了全部的内置变量。这些内置的变量可以在awk程序中引用或修改,例如,你可以利用NR变量在模式匹配中指定工作范围,也可以通过修改记录分隔符RS让一个特殊字符而不是换行符作为记录的分隔符。
例:显示文本文件myfile中第七行到第十五行中以字符%分隔的第一字段,第三字段和第七字段:
awk -F % 'NR==7,NR==15 {printf $1 $3 $7}'
awk的内置函数
awk 之所以成为一种优秀的程序设计语言的原因之一是它吸收了某些优秀的程序设计语言(例如C)语言的许多优点。这些优点之一就是内置函数的使用,awk定义并支持了一系列的内置函数,由于这些函数的使用,使得awk提供的功能更为完善和强大,例如,awk使用了一系列的字符串处理内置函数(这些函数看起来与C 语言的字符串处理函数相似,其使用方式与C语言中的函数也相差无几),正是由于这些内置函数的使用,使awk处理字符串的功能更加强大。本文后面的附录中列有一般的awk所提供的内置函数,这些内置函数也许与你的awk版本有些出入,因此,在使用之前,最好参考一下你的系统中的联机帮助。
作为内置函数的一个例子,我们将在这里介绍awk的printf函数,这个函数使得awk与c语言的输出相一致。实际上,awk中有许多引用形式都是从C语言借用过来的。如果你熟悉C语言,你也许会记得其中的printf函数,它提供的强大格式输出功能曾经带我们许多的方便。幸运的是,我们在awk中又和它重逢了。awk中printf几乎与C语言中一模一样,如果你熟悉C语言的话,你完全可以照C语言的模式使用awk中的printf。因此在这里,我们只给出一个例子,如果你不熟悉的话,请随便找一本C语言的入门书翻翻。
例:显示文件myfile中的行号和第3字段:
$awk '{printf"%03d%s\n",NR,$1}' myfile
在命令行使用awk
按照顺序,我们应当讲解awk程序设计的内容了,但在讲解之前,我们将用一些例子来对前面的知识进行回顾,这些例子都是在命令行中使用的,由此我们可以知道在命令行中使用awk是多么的方便。这样做的原因一方面是为下面的内容作铺垫,另一方面是介绍一些解决简单问题的方法,我们完全没有必要用复杂的方法来解决简单的问题----既然awk提供了较为简单的方法的话。
例:显示文本文件mydoc匹配(含有)字符串"sun"的所有行。
$awk '/sun/{print}' mydoc
由于显示整个记录(全行)是awk的缺省动作,因此可以省略action项。
$awk '/sun/' mydoc
例:下面是一个较为复杂的匹配的示例:
$awk '/[Ss]un/,/[Mm]oon/ {print}' myfile
它将显示第一个匹配Sun或sun的行与第一个匹配Moon或moon的行之间的行,并显示到标准输出上。
例:下面的示例显示了内置变量和内置函数length()的使用:
$awk 'length($0)>80 {print NR}' myfile
该命令行将显示文本myfile中所有超过80个字符的行号,在这里,用$0表示整个记录(行),同时,内置变量NR不使用标志符'$'。
例:作为一个较为实际的例子,我们假设要对UNIX中的用户进行安全性检查,方法是考察/etc下的passwd文件,检查其中的passwd字段(第二字段)是否为"*",如不为"*",则表示该用户没有设置密码,显示出这些用户名(第一字段)。我们可以用如下语句实现:
#awk -F: '$2=="" {printf("%s no password!\n",$1' /etc/passwd
在这个示例中,passwd文件的字段分隔符是“:”,因此,必须用-F:来更改默认的字段分隔符,这个示例中也涉及到了内置函数printf的使用。
awk的变量
如同其它程序设计语言一样,awk允许在程序语言中设置变量,事实上,提供变量的功能是程序设计语言的其本要求,不提供变量的程序设计语言本人还从未见过。
awk 提供两种变量,一种是awk内置的变量,这前面我们已经讲过,需要着重指出的是,与后面提到的其它变量不同的是,在awk程序中引用内置变量不需要使用标志符"$"(回忆一下前面讲过的NR的使用)。awk提供的另一种变量是自定义变量。awk允许用户在awk程序语句中定义并调用自已的变量。当然这种变量不能与内置变量及其它awk保留字相同,在awk中引用自定义变量必须在它前面加上标志符"$"。与C语言不同的是,awk中不需要对变量进行初始化,awk根据其在awk中第一次出现的形式和上下文确定其具体的数据类型。当变量类型不确定时,awk默认其为字符串类型。这里有一个技巧:如果你要让你的awk程序知道你所使用的变量的明确类型,你应当在在程序中给它赋初值。在后面的实例中,我们将用到这一技巧。
运算与判断:
作为一种程序设计语言所应具有的特点之一,awk支持多种运算,这些运算与C语言提供的几本相同:如+、-、*、/、%等等,同时,awk也支持C语言中类似++、--、+=、-=、=+、=-之类的功能,这给熟悉C语言的使用者编写awk程序带来了极大的方便。作为对运算功能的一种扩展,awk还提供了一系列内置的运算函数(如log、sqr、cos、sin等等)和一些用于对字符串进行操作(运算)的函数(如length、substr等等)。这些函数的引用大大的提高了awk的运算功能。
作为对条件转移指令的一部分,关系判断是每种程序设计语言都具备的功能,awk也不例外。awk 中允许进行多种测试,如常用的==(等于)、!=(不等于)、>(大于)、<(小于)、>=(大于等于)、>=(小于等于)等等,同时,作为样式匹配,还提供了~(匹配于)和!~(不匹配于)判断。
作为对测试的一种扩充,awk也支持用逻辑运算符:!(非)、&&(与)、||(或)和括号()进行多重判断,这大大增强了awk的功能。本文的附录中列出了awk所允许的运算、判断以及操作符的优先级。
awk的流程控制
流程控制语句是任何程序设计语言都不能缺少的部分。任何好的语言都有一些执行流程控制的语句。awk提供的完备的流程控制语句类似于C语言,这给我们编程带来了极大的方便。
1、BEGIN和END:
在 awk中两个特别的表达式,BEGIN和END,这两者都可用于pattern中(参考前面的awk语法),提供BEGIN和END的作用是给程序赋予初始状态和在程序结束之后执行一些扫尾的工作。任何在BEGIN之后列出的操作(在{}内)将在awk开始扫描输入之前执行,而END之后列出的操作将在扫描完全部的输入之后执行。因此,通常使用BEGIN来显示变量和预置(初始化)变量,使用END来输出最终结果。
例:累计销售文件xs中的销售金额(假设销售金额在记录的第三字段):
$awk
>'BEGIN { FS=":";print "统计销售金额";total=0}
>{print $3;total=total+$3;}
>END {printf "销售金额总计:%.2f",total}' sx
(注:>是shell提供的第二提示符,如要在shell程序awk语句和awk语言中换行,则需在行尾加反斜杠\)
在这里,BEGIN预置了内部变量FS(字段分隔符)和自定义变量total,同时在扫描之前显示出输出行头。而END则在扫描完成后打印出总合计。
2、流程控制语句
awk提供了完备的流程控制语句,其用法与C语言类似。下面我们一一加以说明:
2.1、if...else语句:
格式:
if(表达式)
语句1
else
语句2
格式中"语句1"可以是多个语句,如果你为了方便awk判断也方便你自已阅读,你最好将多个语句用{}括起来。awk分枝结构允许嵌套,其格式为:
if(表达式1)
{if(表达式2)
语句1
else
语句2
}
语句3
else {if(表达式3)
语句4
else
语句5
}
语句6
当然实际操作过程中你可能不会用到如此复杂的分枝结构,这里只是为了给出其样式罢了。
2.2、while语句
格式为:
while(表达式)
语句
2.3、do-while语句
格式为:
do
{
语句
}while(条件判断语句)
2.4、for语句
格式为:
for(初始表达式;终止条件;步长表达式)
{语句}
在 awk的 while、do-while和for语句中允许使用break,continue语句来控制流程走向,也允许使用exit这样的语句来退出。break 中断当前正在执行的循环并跳到循环外执行下一条语句。continue从当前位置跳到循环开始处执行。对于exit的执行有两种情况:当exit语句不在 END中时,任何操作中的exit命令表现得如同到了文件尾,所有模式或操作执行将停止,END模式中的操作被执行。而出现在END中的exit将导致程序终止。
例:为了
awk中的自定义函数
定义和调用用户自己的函数是几乎每个高级语言都具有的功能,awk也不例外,但原始的awk并不提供函数功能,只有在nawk或较新的awk版本中才可以增加函数。
函数的使用包含两部分:函数的定义与函数调用。其中函数定义又包括要执行的代码(函数本身)和从主程序代码传递到该函数的临时调用。
awk函数的定义方法如下:
function 函数名(参数表){
函数体
}
在gawk中允许将function省略为func,但其它版本的awk不允许。函数名必须是一个合法的标志符,参数表中可以不提供参数(但在调用函数时函数名后的一对括号仍然是不可缺少的),也可以提供一个或多个参数。与C语言相似,awk的参数也是通过值来传递的。
在 awk中调用函数比较简单,其方法与C语言相似,但awk比C语言更为灵活,它不执行参数有效性检查。换句话说,在你调用函数时,可以列出比函数预计(函数定义中规定)的多或少的参数,多余的参数会被awk所忽略,而不足的参数,awk将它们置为缺省值0或空字符串,具体置为何值,将取决于参数的使用方式。
awk函数有两种返回方式:隐式返回和显式返回。当awk执行到函数的结尾时,它自动地返回到调用程序,这是函数是隐式返回的。如果需要在结束之前退出函数,可以明确地使用返回语句提前退出。方法是在函数中使用形如:return 返回值 格式的语句。
例:下面的例子演示了函数的使用。在这个示例中,定义了一个名为print_header的函数,该函数调用了两个参数FileName和 PageNum,FileName参数传给函数当前使用的文件名,PageNum参数是当前页的页号。这个函数的功能是打印(显示)出当前文件的文件名,和当前页的页号。完成这个功能后,这个函数将返回下一页的页号。
nawk
>'BEGIN{pageno=1;file=FILENAME
>pageno=print_header(file,pageno);#调用函数print_header
>printf("当前页页号是:%d\n",pageno);
>}
>#定义函数print_header
>function print_header(FileName,PageNum){
>printf("%s %d\n",FileName,PageNum); >PageNum++;return PageNUm;
>}
>}' myfile
执行这个程序将显示如下内容:
myfile 1
当前页页号是:2
awk高级输入输出
1.读取下一条记录:
awk的next语句导致awk读取下一个记录并完成模式匹配,然后立即执行相应的操作。通常它用匹配的模式执行操作中的代码。next导致这个记录的任何额外匹配模式被忽略。
2.简单地读取一条记录
awk 的 getline语句用于简单地读取一条记录。如果用户有一个数据记录类似两个物理记录,那么getline将尤其有用。它完成一般字段的分离(设置字段变量$0 FNR NF NR)。如果成功则返回1,失败则返回0(到达文件尾)。如果需简单地读取一个文件,则可以编写以下代码:
例:示例getline的使用
{while(getline==1)
{
#process the inputted fields
}
}
也可以使getline保存输入数据在一个字段中,而不是通过使用getline variable的形式处理一般字段。当使用这种方式时,NF被置成0,FNR和NR被增值。
用户也可以使用getline<"filename"方式从一个给定的文件中输入数据,而不是从命令行所列内容输入数据。此时,getline将完成一般字段分离(设置字段变量$0和NF)。如果文件不存在,返回-1,成功,返回1,返回0表示失败。用户可以从给定文件中读取数据到一个变量中,也可以用stdin(标准输入设备)或一个包含这个文件名的变量代替filename。值得注意的是当使用这种方式时不修改FNR和NR。
另一种使用getline语句的方法是从UNIX命令接受输入,例如下面的例子:
例:示例从UNIX命令接受输入
{while("who -u"|getline)
{
#process each line from the who command
}
}
当然,也可以使用如下形式:
"command" | getline variable
3.关闭文件:
awk中允许在程序中关闭一个输入或输出文件,方法是使用awk的close语句。
close("filename")
filename可以是getline打开的文件(也可以是stdin,包含文件名的变量或者getline使用的确切命令)。或一个输出文件(可以是stdout,包含文件名的变量或使用管道的确切命令)。
4.输出到一个文件:
awk中允许用如下方式将结果输出到一个文件:
printf("hello word!\n")>"datafile"
或
printf("hello word!\n")>>"datafile"
5.输出到一个命令
awk中允许用如下方式将结果输出到一个命令:
printf("hello word!\n")|"sort-t','"
awk与shell script混合编程
因为awk可以作为一个shell命令使用,因此awk能与shell批处理程序很好的融合在一起,这给实现awk与shell程序的混合编程提供了可能。实现混合编程的关键是awk与shell script之间的对话,换言之,就是awk与shell script之间的信息交流:awk从shell script中获取所需的信息(通常是变量的值)、在awk中执行shell命令行、shell script将命令执行的结果送给awk处理以及shell script读取awk的执行结果等等。
1.awk读取Shell script程序变量
在awk中我们可以通过“'$变量名'”的方式读取sell scrpit程序中的变量。
例:在下面的示例中,我们将读取sell scrpit程序中的变量Name,该变量存放的是文本myfile的撰写者,awk将打印出这个人名。
$cat writename
:
# @(#)
#
.
.
.
Name="张三" nawk 'BEGIN {name="'Name'";\ printf("\t%s\t撰写者%s\n",FILENAME,name");}\
{...}END{...}' myfile
.
.
.
2.将shell命令的执行结果送给awk处理
作为信息传送的一种方法,我们可以将一条shell命令的结果通过管道线(|)传递给awk处理:
例:示例awk处理shell命令的执行结果
$who -u | awk '{printf("%s正在执行%s\n",$2,$1)}'
该命令将打印出注册终端正在执行的程序名。
3.shell script程序读awk的执行结果
为了实现shell script程序读取awk执行的结果,我们可以采取一些特殊的方法,例如我们可以用变量名=`awk语句`的形式将awk执行的结果存放入一个 shell script变量。当然也可以用管道线的方法将awk执行结果传递给shell script程序处理。
例:作为传送消息的机制之一,UNIX提供了一个向其所有用户传送消息的命令wall(意思是write to all写给所有用户),该命令允许向所有工作中的用户(终端)发送消息。为此,我们可以通过一段shell批处理程序wall.shell来模拟这一程序(事实上比较老的版本中wall就是一段shell批处理程序:
$cat wall.shell
:
# @(#) wall.shell:发送消息给每个已注册终端
#
cat >/tmp/$$
#用户录入消息文本 who -u | awk '{print $2}' | while read tty
do
cat /tmp/$$>$tty
done
在这个程序里,awk接受who -u命令的执行结果,该命令打印出所有已注册终端的信息,其中第二个字段是已注册终端的设备名,因此用awk命令析出该设备名,然后用while read tty语句循环读出这些文件名到变量(shell script变量)tty中,作为信息传送的终结地址。
4.在awk中执行shell命令行----嵌入函数system()
system()是一个不适合字符或数字类型的嵌入函数,该函数的功能是处理作为参数传递给它的字符串。system对这个参数的处理就是将其作为命令处理,也就是说将其当作命令行一样加以执行。这使得用户在自己的awk程序需要时可以灵活地执行命令或脚本。
例:下面的程序将使用system嵌入函数打印用户编制好的报表文件,这个文件存放在名为myreport.txt的文件中。为简约起见,我们只列出了其END部分:
.
.
.
END {close("myreport.txt");system("lp myreport.txt");}
在这个示例中,我们首先使用close语句关闭了文件myreport.txt文件,然后使用system嵌入函数将myreport.txt送入打印机打印。
写到这里,我不得不跟朋友们说再见了,实在地说,这些内容仍然是awk的初步知识,电脑永远是前进的科学,awk也不例外,本篇所能做的只是在你前行的漫漫长途中铺平一段小小开端,剩下的路还得靠你自己去走。老实说,如果本文真能给你前行的路上带来些许的方便,那本人就知足了!
如对本篇有任何疑问,请E-mail To:Chizlong@yeah.net或到主页http://chizling.yeah.net中留言。
附录:
1.awk的常规表达式元字符
\ 换码序列
^ 在字符串的开头开始匹配
$ 在字符串的结尾开始匹配
. 与任何单个字符串匹配
[ABC] 与[]内的任一字符匹配
[A-Ca-c] 与A-C及a-c范围内的字符匹配(按字母表顺序)
[^ABC] 与除[]内的所有字符以外的任一字符匹配
Desk|Chair 与Desk和Chair中的任一个匹配
[ABC][DEF] 关联。与A、B、C中的任一字符匹配,且其后要跟D、E、F中的任一个字符。
* 与A、B或C中任一个出现0次或多次的字符相匹配
+ 与A、B或C中任何一个出现1次或多次的字符相匹配
? 与一个空串或A、B或C在任何一个字符相匹配
(Blue|Black)berry 合并常规表达式,与Blueberry或Blackberry相匹配
2.awk算术运算符
运算符 用途
------------------
x^y x的y次幂
x**y 同上
x%y 计算x/y的余数(求模)
x+y x加y
x-y x减y
x*y x乘y
x/y x除y
-y 负y(y的开关符号);也称一目减
++y y加1后使用y(前置加)
y++ 使用y值后加1(后缀加)
--y y减1后使用y(前置减)
y-- 使用后y减1(后缀减)
x=y 将y的值赋给x
x+=y 将x+y的值赋给x
x-=y 将x-y的值赋给x
x*=y 将x*y的值赋给x
x/=y 将x/y的值赋给x x%=y 将x%y的值赋给x
x^=y 将x^y的值赋给x
x**=y 将x**y的值赋给x
3.awk允许的测试:
操作符 含义
x==y x等于y
x!=y x不等于y
x>y x大于y
x>=y x大于或等于y
x<=y x小于或等于y? x~re x匹配正则表达式re? x!~re x不匹配正则表达式re?
4.awk的操作符(按优先级升序排列)
= 、+=、 -=、 *= 、/= 、 %=
||
&&
> >= < <= == != ~(匹配于) !~(不匹配于) xy (字符串连结,'x''y'变成"xy") + - * / % ++ --
5.awk内置变量(预定义变量)
说明:表中v项表示第一个支持变量的工具(下同):A=awk,N=nawk,P=POSIX awk,G=gawk
V 变量 含义 缺省值
--------------------------------------------------------
N ARGC 命令行参数个数
G ARGIND 当前被处理文件的ARGV标志符
N ARGV 命令行参数数组
G CONVFMT 数字转换格式 %.6g
P ENVIRON UNIX环境变量
N ERRNO UNIX系统错误消息
G FIELDWIDTHS 输入字段宽度的空白分隔字符串
A FILENAME 当前输入文件的名字
P FNR 当前记录数
A FS 输入字段分隔符 空格
G IGNORECASE 控制大小写敏感0(大小写敏感)
A NF 当前记录中的字段个数
A NR 已经读出的记录数
A OFMT 数字的输出格式 %.6g
A OFS 输出字段分隔符 空格
A ORS 输出的记录分隔符 新行
A RS 输入的记录他隔符 新行
N RSTART 被匹配函数匹配的字符串首
N RLENGTH 被匹配函数匹配的字符串长度
N SUBSEP 下标分隔符 "\034"
6.awk的内置函数
V 函数 用途或返回值
------------------------------------------------
N gsub(reg,string,target) 每次常规表达式reg匹配时替换target中的string
N index(search,string) 返回string中search串的位置
A length(string) 求串string中的字符个数
N match(string,reg) 返回常规表达式reg匹配的string中的位置
N printf(format,variable) 格式化输出,按format提供的格式输出变量variable。
N split(string,store,delim) 根据分界符delim,分解string为store的数组元素
N sprintf(format,variable) 返回一个包含基于format的格式化数据,variables是要放到串中的数据
G strftime(format,timestamp) 返回一个基于format的日期或者时间串,timestmp是systime()函数返回的时间
N sub(reg,string,target) 第一次当常规表达式reg匹配,替换target串中的字符串
A substr(string,position,len) 返回一个以position开始len个字符的子串
P totower(string) 返回string中对应的小写字符
P toupper(string) 返回string中对应的大写字符
A atan(x,y) x的余切(弧度)
N cos(x) x的余弦(弧度)
A exp(x) e的x幂
A int(x) x的整数部分
A log(x) x的自然对数值
N rand() 0-1之间的随机数
N sin(x) x的正弦(弧度)
A sqrt(x) x的平方根
A srand(x) 初始化随机数发生器。如果忽略x,则使用system()
G system() 返回自1970年1月1日以来经过的时间(按秒计算)
其他:IBM awk教程
http://www.ibm.com/developerworks/cn/linux/shell/awk/awk-2/#h3
百度百科 awk
http://baike.baidu.com/view/209681.htm
Saturday, May 09, 2009
(转)Sort命令
Sort命令将逐行对文件中的内容进行排序,如果两行的首字符相同,该命令将继续比较这两行的下一个字符,如果还相同,将继续进行比较。
语法:
sort [选项]文件
说明:sort命令对指定文件中所有的行进行排序,并将结果显示在标准输出上。如不指定输入文件或使用“-”,则表示排序内容来自标准输入。
sort排序是根据从输入行抽取的一个或多个关键字进行比较来完成的。排序关键字定义了用来排序的最小的字符序列。默认情况下以整行为关键字按ASCII字符顺序进行排序。
改变默认设置的选项主要有:
- m 若给定文件已排好序,合并文件。
- c 检查给定文件是否已排好序,如果它们没有都排好序,则显示一个出错信息,并以状态值1退出。
- u 对排序后认为相同的行只留其中一行。
- o 输出文件将排序输出写到输出文件中而不是标准输出,如果输出文件是输入文件之一,sort先将该文件的内容写入一个暂存文件,然后再排序并写输出结果。
改变默认排序规则的选项主要有:
- d 按字典顺序排序,比较时仅字母、数位、空格和跳位字符有意义。
- f 将小写字母与大写字母同等对待。
- I 忽略非显示字符。
- M 作为月份比较。
- r 按逆序输出排序结果。
+posl - pos2 指定一个或几个栏位作为排序关键字,栏位位置从posl开始,到pos2结束(包括posl,不包括pos2)。如不指定pos2,则关键字为从posl到行尾。栏位和字符的位置从0开始。
- b 在每行中寻找排序关键字时忽略前导的空白(空格和跳位字符)。
- t separator 指定字符separator作为栏位分隔符号。
下面通过几个例子来讲述sort的使用。
用sort命令对text文件中各行排序后输出其结果。请注意,在原文件的第2, 3行上的第1个单词完全相同,该命令将从它们的第2个单词vegetables与fruit的首字符处继续进行比较。
$ cat text
vegetable soup
fresh vegetables
fresh fruit
lowfat milk
$ sort text
fresh fruit
fresh vegetables
lowfat milk
vegetable soup
用户可以保存排序后的文件内容,或把排序后的文件内容输出至打印机。下例中用户把排序后的文件内容保存到名为result的文件中。
$ sort text>result
以第2个栏位作为排序关键字对文件example的内容进行排序。
$ sort +1-2 example
对于file1和file2文件内容反向排序,结果放在outfile中,利用第2个栏位的第一个字符作为排序关键字。
$ sort -r -o outfile +1.0 -1.1 example
sort排序常用于在管道中与其他命令组合,完成比较复杂的功能。如利用管道将当前工作目录中的文件送给sort进行排序,排序关键字是第6个~第8个栏位。
$ ls - l | sort +5 – 7
sort命令也可以对标准输入进行操作。例如,如果您想把几个文件文本行合并,并对合并后的文本行进行排序,您可以首先用命令cat把多个文件 合并,然后用管道操作把合并后的文本行输入给命令sort,sort命令将输出这些合并及排序后的文本行。在下面的例子中,文件veglist与文件 fruitlist的文本行经过合并与排序后被保存到文件clist中。
$ cat veglist fruitlist | sort > clist
(转)find命令
语法:find 起始目录 寻找条件 操作
说明:find命令从指定的起始目录开始,递归搜索其各个子目录,查找满足寻找条件的文件并对之采取相关的操作。
该命令提供的寻找条件可以是一个用逻辑运算符not, and, or组成的复合条件。逻辑运算符and, or, not的含义为:
(1)and:逻辑与,在命令中用-a表示,是系统默认的选项,表示只有当所给的条件都满足时,寻找条件才算满足。例如:
$ find –name 'tmp' –xtype c -user 'inin'
该命令寻找满足3个给定条件的所有文件。
(2)or:逻辑或,在命令中用-o表示。该运算符表示只要所给的条件中有一个满足时,寻找条件就算满足。例如:
$ find –name 'tmp' –o –name 'mina*'
该命令查询文件名为tmp或是匹配mina*的所有文件。
(3)not:逻辑非,在命令中用!表示。该运算符表示查找不满足所给条件的文件。例如:
$ find ! –name 'tmp'
该命令查询文件名不是tmp的所有文件。
需要说明的是:当使用很多的逻辑选项时,可以用括弧把这些选项括起来。为了避免Shell本身对括弧引起误解,在括号前需要加转义字符“\”来去除括弧的意义。如:
$ find \(–name 'tmp' –xtype c -user 'inin' \)
寻找条件有以下选项:
首先,下列各个选项中的n值可以有3种输入方式,假设n为20,则:
+20 表示20以后(21, 22, 23等)
-20 表示20以前(19, 18, 17等)
20 表示正好是20
(1)以名称和文件属性查找。
- name '字串' 查找文件名匹配所给字串的所有文件,字串内可用万用字符*, ?, [ ]。
- lname '字串' 查找文件名匹配所给字串的所有符号链接文件,字串内可用万用字符*, ?, [ ]。
-gid n 查找属于ID号为n的用户组的所有文件。
-uid n 查找属于ID号为n的用户的所有文件。
-group '字串' 查找属于用户组名为所给字串的所有文件。
-user '字串' 查找属于用户名为所给字串的所有文件。
-empty 查找大小为0的目录或文件。
-path '字串' 查找路径名匹配所给字串的所有文件,字串内可用万用字符*, ?, [ ]。
-perm 许可权 查找具有指定许可权的文件和目录,许可权的表示可以如711, 644。
-size n[bckw] 查找指定大小的文件,n后面的字符表示单位,默认为b,代表512字节的块。
-type x 查找类型为x的文件,x为下列字符之一:
b 块设备文件;
c 字符设备文件 ;
d 目录文件;
p 具名管道(FIFO);
f 普通文件;
l 符号链接文件(symbolic links);
s socket文件。
-xtype x 与-type基本相同,但只查找符号链接文件。
(2)以时间为条件查找。
- amin n 查找n分钟以前被访问过的所有文件。
- atime n 查找n天以前被访问过的所有文件。
- cmin n 查找n分钟以前文件状态被修改过的所有文件。
- ctime n 查找n天以前文件状态被修改过的所有文件。
- mmin n 查找n分钟以前文件内容被修改过的所有文件。
- mtime n 查找n天以前文件内容被修改过的所有文件。
(3)可执行的操作。
- exec 命令名称 {} 对符合条件的文件执行所给的Linux 命令,而不询问用户是否需要执行该命令。{}表示命令的参数,即所找到的文件;命令的末尾必须以“ \;”结束。
- ok 命令名称 { } 对符合条件的文件执行所给的Linux 命令,与exec不同的是,它会询问用户是否需要执行该命令。
- ls 详细列出所找到的所有文件。
- fprintf 文件名 将找到的文件名写入指定文件。
- print 在标准输出设备上显示查找出的文件名。
- printf 格式 格式的写法请参考有关C语言的图书。
例10-11:查找当前目录中所有以main开头的文件,并显示这些文件的内容。
$ find . - name 'main*' - exec more {} \;
例10-12:删除当前目录下所有一周之内没有被访问过的a .out或*.o文件。
$ find . \(- name a.out - o - name '*.o'\)\
> - atime +7 - exec rm {} \;
说明如下:
命令中的“.”表示当前目录,此时find将从当前目录开始,逐个在其子目录中查找满足后面指定条件的文件。\(和\)表示括弧(),其中的“ \”称为转义符。之所以这样写是由于对Shell而言,(和)另有不同的含义,而不是这里的用于组合条件的用途。- name a.out是指要查找名为a.out的文件;- name '*.o'指要查找所有名字以 .o结尾的文件。这两个- name之间的- o表示逻辑或(or),即查找名字为a.out或名字以 .o结尾的文件,find在当前目录及其子目录下找到这样的文件之后,再进行判断,看其最后访问时间是否在7天以前,若是,则对该文件执行命令(- exec rm{ }\;)。其中{ }代表当前查到的符合条件的文件名,“\;”则是语法所要求的。上述命令中第一行的最后一个“\”是续行符。当命令太长而在一行写不下时,可输入一个“ \”,之后系统将显示一个“>”,指示用户继续输入命令。
(转)grep, egrep, fgrep命令
知道什么是grep吗?Global Regular Expression Print,每个词首字节的缩写。
这组命令以指定模式搜索文件(模式是什么,别急看看例子), 并通知用户在什么文件中搜索到与指定的模式匹配的字符串, 并打印出所有包含该字符串的文本行, 在该文本行的最前面是该行所在的文件名. 其三者的区别是
- grep命令一次只能搜索一个指定的模式,如df -k | grep -v '/dev';
- egrep命令检索扩展的正则表达式(包括表达式组和可选项) ,如df -k | egrep -v '/dev|/mnt' ;
- fgrep命令检索固定字符串,它不识别正则表达式,是快速搜索命令.
该组命令中的每一个命令都有一组选项,利用这些选项可以改变其输出方式. 例如,可以在搜索到的文本行上加行号,或者只输出文本行的行号, 或者输出所有与搜索模式不匹配的文本行,或只简单地输出已搜索到 指定模式的文件名,并且可以指定在查找模式时忽略大小写.
这组命令在指定的输入文件中查找与模式匹配的行.如果没有指定文件,则从标准输入中读取.正常情况下,每个匹配的行显示到标准输出.如果要 查找的文件是多个,则在每一行输出之前加上文件名.
语法∶
- grep [选项] [查找模式] [文件名1,文件名2,……]
- egrep [选项] [查找模式] [文件名1,文件名2,……]
- fgrep [选项] [查找模式] [文件名1,文件名2,……]
这组命令各个选项的含义为∶
- E 每个模式作为一个扩展的正则表达式对待.
- F 每个模式作为一组固定字符串对待(以新行分隔),而不作为正则表达式.
- b 在输出的每一行前显示包含匹配字符串的行在文件中的字节偏移量.
- c 只显示匹配行的数量.
- i 比较时不区分大小写.
- h 在查找多个文件时,指示grep不要将文件名加入到输出之前.
- l 显示首次匹配串所在的文件名并用换行符将其隔开.当在某文件中多次出现匹配串时,不重复显示此文件名.
- n 在输出前加上匹配串所在行的行号(文件首行行号为1).
- v 只显示不包含匹配串的行.
- x 只显示整行严格匹配的行.
- e expression 指定检索使用的模式.用于防止以“-”开头的模式被解释为命令选项.
- f expfile 从expfile文件中获取要搜索的模式,一个模式占一行.
对该组命令的使用还需注意以下方面∶
- 在命令后键入搜索的模式,再键入要搜索的文件. 其中,文件名列表中也可以使用特殊字符, 如“*”可以生成全部文件的文件名列表.
- 如果想在搜索模式中包含有空格的字符串,可以用单引号把要搜索的模式括起来,用来表明搜索的模式是由包含空格的字符串组成. 否则,Shell将把空格认为是命令行参数的定界符,而grep命令将把搜索模式中的单词解释为文件名列表中的一部分.
爱了,痛了,累了,忘了
半年以来,一切都象是昨天发生的事。每天都回忆着的你的哭与笑,这个心结越结越紧,已经让我无法透气。既不回头,何必不忘。从此我也不愿再提,不愿再想。两年前的事情让它成为一片空白,从此不会有人再双眼浮肿。
真的累了,我的生活还得继续下去。你说过,既然做出了决定,就不会再后悔。从此,一个人好好活。
Tuesday, May 05, 2009
(转)Mplayer另类在线播放影音文件技巧
本文介绍的Mplayer在线播放的方法,不是指在浏览器中安装Mplayer插件这种方法,而是在命令行中操作,利用Mplayer的可以从Stdin 中播放的原理实现的。其原理是利用支持Stdout的下载软件(如Wget和Curl),将文件下载到Stdout中;再用Mplayer从Stdin读取数据并播放。由于所有数据都只临时存在于Stdin/Out中,从而可以做到不用在本地硬盘保存,在线播放影音文件。这个方法可以通用于各种发行版。关于Stdin/Out的更多信息,请在网上查阅,我并不是很清楚。
下面,以使用Wget和Mplayer为例,介绍几种比较常见的在线播放的例子。
1、在线播放rmvb文件
这个是最简单的,因为rmvb文件不牵涉到字幕问题。请先确定你已经安装realcodecs。假设我想看某一电影ftp里的某个rmvb电影,那么命令行格式为:
wget ftp://username:password@ftpserver/directory/movie.rmvb -O - | mplayer -cache 8192 -
解释一下,wget的参数“-O”是指另存为,后面的“-”就是指输出到StdOut;“|”是管道符,-cache 8192设置mplayer的缓冲区大小为8192K,最后的“-”告诉Mplayer从StdIn读数据。一般来说,流畅播放需要的带宽为60KB/s 左右。如果网速飞快的话,Mplayer会自动控制wget降速,以保持缓冲区在49%左右。
2、在线播放avi文件
这种文件一般都有单独的字幕文件。字幕文件是需要下载到本地硬盘的,把字幕文件放到StdIn中是不可以的。字幕一般有两个格式,srt和sub。对于srt字幕,假设存放位置为tmp/movie.srt,则总的命令行格式为
wget ftp://username:password@ftpserver/directory/movie.avi -O - | mplayer -cache 8192 -sub tmp/movie.srt -font /usr/share/fonts/simsun.ttf -subcp cp936 -
解释一下,Mplayer的“-sub”指定字幕文件,“-font”指定字幕文件的字体,这里的simsun.ttf对应简体宋体,繁体字幕就换繁体字体文件。“-subcp”指定字幕文件的编码,简体就是cp936,繁体就是big5。
对于sub格式字幕,需要下载movie.sub和movie.idx文件,总的命令行格式为
wget ftp://username:password@ftpserver/directory/movie.avi -O - | mplayer -cache 8192 -vobsub movie -
注意,这里“-vobsub”指定sub格式的字幕,后面只需要字幕文件的前缀名,后缀名不要!!“-font”和“-subcp”参数都用不着,因为sub字幕是特殊位图格式,跟字体和编码都没有关系。
一般来说,流畅播放需要的带宽为130KB/s左右。关于加载字幕的问题,可以参见我的另外一篇文章
http://www.linuxsir.org/bbs/showthread.php?t=249835
3、在线听歌
在线听歌也有几种方法,例如听某个ftp服务器某一目录的所有歌,那个格式就是:
wget ftp://username:password@ftpserver/directory/*.mp3 -O - | mplayer -cache 1000 -
如果某首歌的文件名中有中文,那这首歌就播不了了。这跟wget如何获取列表有关。
有很多音乐网站,也提供在线听歌(比如http://music.trueice.net),点击播放后,会生成一个列表文件(假设报存在tmp/playlist.m3u),这样就可以让wget读取这个列表文件并下载,格式为:
wget -i tmp/playlist.m3u -O - | mplayer -cache 1000 -
如果这样的网站需要登录后才能播放,也就是需要Cookies(比如http://music.xjtust.com),那也没关系,命令格式如下:
wget -i tmp/playlist.m3u –load-cookies .mozilla/firefox/default/cookies.txt - O | mplayer -cache 1000 -
这里,“–load-cookies”后面跟的就是Firefox存放Cookies的文件。
还有些网站,必须用Winamp才能播放,XMMS都不行,那也没有问题,命令格式如下:
wget -i tmp/playlist.m3u –load-cookies .mozilla/firefox/default/cookies.txt –user-agent=”WinampMPEG/5.0″ - O | mplayer -cache 1000 -
这样就会向服务器发送Winamp的播放器标识。
一般来说,流畅播放的带宽为20KB/s左右。
4、其它
wget 还有一个参数在连接ftp服务器的时候也很有用,就是“–no-passive-ftp”。顾名思义,不加这个参数就是Passive模式,加上就是Port模式。如果在播放过程中,wget速度变为0了,可以试试加上或者去掉这个参数。
在播放mp3文件列表时,有可能出现wget在下载其中的一个文件,但是mplayer就是不播放它。这是因为由于mplayer默认从文件的扩展名判断其音频解码类型,而可能由于文件名编码的问题,在stdin中找不到相关信息。这样mplayer就可能不知道如何解码而拒绝播放。可以在mplayer 后面增加这样一个参数“-demuxer 17”,强制它按音频格式处理。
使用curl播放的基本命令为:
curl url -o - | mplayer -cache -
注意是curl另存的参数为小写o,但是curl是否支持Cookies以及是否可以设定user-agent没有试过
----------added by l0he1g 2009/5/8 东北大学电台收听脚本---------------
#!/bin/bash
chanel1=http://radio.neu6.edu.cn:8000/kcrw
chanel2=http://radio.neu6.edu.cn:8000/foxnews
chanel3=http://radio.neu6.edu.cn:8000/rsc
chanel4=http://radio.neu6.edu.cn:8000/rsp
chanel5=http://radio.neu6.edu.cn:8000/rsj
chanel6=http://radio.neu6.edu.cn:8000/558am
chanel7=http://radio.neu6.edu.cn:8000/998fm
chanel8=http://radio.neu6.edu.cn:8000/ccm
chanel9=http://radio.neu6.edu.cn:8000/onair
chanel10=http://radio.neu6.edu.cn:8000/tnccp
chanel11=http://radio.neu6.edu.cn:8000/onefm
if [ $# -eq 0 ];then
echo "Useage:radio.sh n"
echo "n is a digit as fowllowing:"
echo "1:Radio Swiss Pop"
echo "2:KCRW World News"
echo "3:Fox News Talk"
echo "4:Radio Swiss Classic"
echo "5:Radio Swiss Jazz"
echo "6:988FM Radio Station Malaysia"
echo "7:Spectrum Chinese Community Network 558AM"
echo "8:Chinese Classical Music"
echo "9:on air POWER webcast - 24 hours a day Chinese radio station"
echo "10:The Noise Club-Chinese Pop"
echo "11:ONE FM - You're My No.1: One FM"
else
eval ch="$"chanel$1
echo $ch
wget $ch -O -| mplayer -demuxer 17 -cache 30 -
fi
To-do
- Only think things in down the line
- lab:ROCK parallelize
- study:devel into dm
- health:insist on exercise
- data mining course project