发布新日志

  • Ruby语言入门(17)- 内部类 -File

    2013-02-05 14:08:23

    File类是访问文件用的类。通常使用open或File.open来生成。

    类方法

    File.atime(filename)
    File.ctime(filename)
    File.mtime(filename)
    它们分别返回:文件的最终访问时间/文件状态的最终变更时间/最终更新时间(Time对象)。

    File.atime("c:\\test.txt")
    =>2013-02-04 18:40:21 +0800
    File.ctime("c:\\test.txt")
    =>2013-02-04 16:33:08 +0800
    File.mtime("c:\\test.txt")
    =>2013-02-04 17:08:40 +0800

    File.basename(filename[, suffix])
    返回filename中的最后一条斜线后面的部分。若给出了参数suffix且它和filename的尾部一致时,该方法会将其删除并返回结果。

    File.basename("c:\\test.txt")        
    => "test.txt"
    File.basename("c:\\test.txt", "txt")  
    => "test."
    File.basename("c:\\test.txt", ".*")  
    => "test"
    File.basename("c:\\test.txt", ".")  
    => "test.txt"

    File.dirname(filename)
    以字符串的形式返回filename中最后一条斜线之前的部分。若文件名中不含斜线,则返回"."(当前目录)。

    File.dirname("c:\\test.txt")        
    => "c:\\"

    File.extname(filename)
    返回文件名filename中的扩展名部分(跟在最后的"."之后的部分)。目录名中的"."和文件名头上的"."不会被看作扩展名的一部分。若filename中不含扩展名则返回空字符串。

    File.extname("c:\\test.txt")        
    => ".txt"
    File.extname("c:/test.txt")        
    => ".txt"
    File.extname("c:/test")        
    => ""

    (在windows的irb下,\\ 等同于 /)

    File.chmod(mode[, filename[, ...]])
    File.lchmod(mode[, filename[, ...]])
    将文件的模式改为mode。它返回修改文件的个数。lchmod只修改符号连接中的连接本身的模式。

    mode可以是:
    "r", RDONLY: 以读取模式打开文件.
    "w", WRONLY|CREAT|TRUNC: 以写入模式打开文件.打开文件时,若文件已存在就清空文件内容.
    "a", WRONLY|CREAT|APPEND: 以写入模式打开文件.通常把写入内容添加到文件结尾.

    若有"+"的话,就以读写两用模式(RDWR)打开文件.
    "r+": 将文件的读写位置设在开头.
    "w+": 与"r+"一样.打开文件时,若文件已存在就清空其内容.
    "a+": 与"r+"一样.打开文件时,若文件已存在,就把读写位置设在文件结尾.


    File.chown(owner, group[, filename[, ...]])
    File.lchown(owner, group[, filename[, ...]])
    修改文件的owner和group。只有超级用户才能修改文件的owner和group。它返回修改文件的个数。lchown只修改符号连接中的连接本身的owner和group。

    File.delete(filename ... )
    File.unlink(filename ... )
    删除文件。返回删除文件的个数。该方法是用来删除普通文件的。而删除目录时要使用Dir.rmdir。

    File.delete("c:\\test.txt")
    =>1
    File.delete("c:\\test.txt", "c:\\test1.txt", "c:\\test2.txt")
    =>3

    File.expand_path(path[, default_dir])
    将path展开为绝对路径后返回该路径字符串。若path是相对路径则以default_dir为基准进行扩展。若没有default_dir或其值为nil时将使用当前目录。

    File.expand_path(("c:/test.txt")
    =>"c:/test.txt"
    File.expand_path((".")
    =>"c:/Sites"
    File.expand_path(("..")
    =>"c:/"

    File.fnmatch(pattern, path[, flags])
    File.fnmatch?(pattern, path[, flags])
    对文件名进行模式匹配(fnmatch(3))。若path与pattern相匹配则返回真。

    File.fnmatch("*", "c:/test.txt")
    =>true
    File.fnmatch("c:/*", "c:/test.txt")
    =>true
    File.fnmatch("c:/", "c:/test.txt")
    =>false

    flags中可以任意使用下列常数(定义在File::Constants模块中)中的若干个来改变模式匹配的运作情况。flags的默认值为0(不指定标识)。

    FNM_NOESCAPE 将转义字符`\'看作普通字符。
    File.fnmatch('\*', '\a')                       
    => false
    File.fnmatch('\*', '\a', File::FNM_NOESCAPE)  
    => true

    FNM_PATHNAME 通配符'*', '?', '[]'将不再匹配'/'
    FNM_CASEFOLD 进行匹配时,不区分大小写字母
    FNM_DOTMATCH 通配符'*', '?', '[]'将匹配于开头的'.'

    File.ftype(filename)
    返回表示文件类型的字符串。该字符串应为下列之一:
    "file"
    "directory"
    "characterSpecial"
    "blockSpecial"
    "fifo"
    "link" (若为符号连接则返回"link")。
    "socket"
    "unknown"

    File.ftype("c:/test.txt")
    =>"file"
    File.ftype("c:")
    =>"directory"

    File.join(item, item, ...)
    将File::SEPARATOR置入其中连成字符串

    a="c:/"
    b="test.txt"
    c=File.join(a, b)
    =>"c:/test.txt"

    File.link(old, new)
    生成一个指向old且名为new的硬连接(hard link)。old必须是现存的。

    File.link("c:/test.txt", "c:/test1.txt")
    =>0
    (在c:下生成新文件test1.txt)

    File.new(path[, mode [, perm]])
    File.open(path[, mode [, perm]])
    File.open(path[, mode [, perm]]) {|file| ... }
    打开path所指文件并返回文件对象。

    mode可以是:
    "r", RDONLY: 以读取模式打开文件.
    "w", WRONLY|CREAT|TRUNC: 以写入模式打开文件.打开文件时,若文件已存在就清空文件内容.
    "a", WRONLY|CREAT|APPEND: 以写入模式打开文件.通常把写入内容添加到文件结尾.

    若有"+"的话,就以读写两用模式(RDWR)打开文件.
    "r+": 将文件的读写位置设在开头.
    "w+": 与"r+"一样.打开文件时,若文件已存在就清空其内容.
    "a+": 与"r+"一样.打开文件时,若文件已存在,就把读写位置设在文件结尾.

    File.readlink(path)
    以字符串形式返回字符连接的连接对象。


    File.rename(from, to)
    修改文件名称。若目录不同时,将进行移动

    File.split(pathname)
    将pathname分为dirname和basename,并返回一个包含这两部分的数组

    File.split("c:/test.txt")
    =>["c:","test.text"]

    File.stat(filename)
    File.lstat(filename)
    生成并返回一个包含filename信息的File::Stat对象。

    File.symlink(old, new)
    生成一个指向old且名为new的符号连接。

    File.truncate(path, length)
    将path所指文件裁减为至多length字节的文件。

    File.umask([umask])
    修改umask。返回修改前的umask值。若省略umask则不修改,返回当前的umask值。

    File.utime(atime, mtime[, filename[, ...]])
    修改文件的最终访问时间和更新时间。返回修改的文件数。

    File.blockdev?(path)
    File.chardev?(path)
    File.directory?(path)
    File.executable?(path)
    File.executable_real?(path)
    File.exist?(path)
    File.file?(path)
    File.grpowned?(path)
    File.owned?(path)
    File.pipe?(path)
    File.readable?(path)
    File.readable_real?(path)
    File.setgid?(path)
    File.setuid?(path)
    File.size(path)
    File.size?(path)
    File.socket?(path)
    File.sticky?(path)
    File.symlink?(path)
    File.writable?(path)
    File.writable_real?(path)
    File.zero?(path)
    判断指定文件的一些属性和判断。

    实例方法

    atime
    ctime
    mtime
    它们分别返回:文件的最终访问时间/文件状态的最终变更时间/最终更新时间

    myfile = File.new("c:/test.txt")
    myflie.atime
    =>2013-02-04 18:40:21 +0800

    chmod(mode)
    将文件模式修改为mode.若修改成功则返回0.

    myfile.chmod(112211)
    =>0

    chown(owner, group)
    修改文件的owner和group.只有超级用户才能修改文件的owner和group.修改成功则返回0.

    myfile.chown(1, 223)
    =>0

    flock(operation)
    锁定文件. 锁定成功时返回0.可用的operation列表:
    LOCK_SH 共享锁. 若干个进程可同时共享锁定.
    LOCK_EX 排它锁.在某时刻,只有一个进程能控制锁.
    LOCK_UN 解锁.
    LOCK_NB 非阻塞模式.

    myfile.flock(File::LOCK_SH)
    =>0

    path
    以字符串形式返回打开文件时使用的路径.

    myfile.path
    =>"c:/test.txt"

    lstat
    生成并返回一个包含文件状态信息的File::Stat对象

    myfile.lstat
    => #<File::Stat dev=0x0 ..... +0800?

    truncate(length)
    将文件裁剪成至多length字节大小的文件.

    myfile.truncate(10240)
    =>0

    常数:

    ALT_SEPARATOR
    当系统的文件路径分隔符与SEPARATOR不同时,即可使用该常数.在MS-DOS等系统中是"\",而在UNIX 或Cygwin等系统中则是nil.

    PATH_SEPARATOR
    PATH环境变量的元素分隔符.在UNIX中是":",而在MS-DOS等系统中是";".

    SEPARATOR
    Separator
    文件路径的分隔符. 例如,在将路径名传给处理文件的方法时就会用到它. 该分隔符使得脚本内的路径名的格式统一且不受环境的影响.其值为"/".

    File::PATH_SEPARATOR
    =>";"


  • 让测试团队慢慢死去?

    2013-02-04 17:52:06

    哈哈,n久前就有人跟我说这个文章了,说实话,一直懒得看,今天有时间,咱也搞个辩论,直接copy过来,红色的是个人意见。

    让测试团队慢慢死去!
    (首先什么叫测试团队呢?有独立的测试部门,测试组,测试人员,从来没听说过独立的测试团队,就算是纯粹的测试外包,也是作为项目团队的一部分,项目团队可不是由开发团队和测试团队构成的,是由各个不同的角色构成的,如果你连这个基本概念都混淆,就不用往下看了,何必呢,有着时间干点别的去吧。)


    让我们先由2个问题引出今天的话题,第一,为什么选择做测试?第二,做测试的发展又如何?
    第一个问题,你为什么要选择做测试,我敢说十个人有九个不会说实话,什么测试能够让我开阔视野啦,测试同样也需要很好的技术啦,,,全是虚伪的借口。真正地答案只有一个,测试的收入高,要求低!(注意是相对你的能力比来说收入算高,因为你要是选择做开发,肯定不如现在的收入)不管你愿不愿意承认你都得承认,这是绝大部分测试入这一行的原因。
    (01年开始做测试的,那个时候根本不了解什么叫测试,很多外界人以为就是点点点,所以自己也这么稀里糊涂的加入,倒不是因为钱多,是因为当时的经理说了一句话,开发都是盲目的实现功能,测试是保证开发是盲目而不是盲动,说实话,这句话过了4,5年才真正理解)BTW,那个时候开发是3k,测试是1.5k,哥就是傻乎乎的被人忽悠入行的。

    第一个问题的答案决定了一个事实,测试团队的发展永远不可能像开发团队一样,随着公司的发展而发展,为什么呢?成本! 世界上没有傻逼的公司,你的公司之所以能够存在,是因为它善于控制成本。站在管理层来看,测试团队是一个"显著"消耗成本而又不"显著"创造价值的团队。
    (这个问题其实已经不是偏激了,纯粹是不懂,测试的目的是保证质量,带来的效果就是减少盲目的开发成本,你要是见识过太极开发了个项目化了2年,为了补bug花了三年就知道了,高质量的测试带来的绝对是最优化的资源成本,你们公司老板连这个都不知道,何必招开发呢,找几个hr mm没事点点点就行了,中软当初就这么干过)

    第二个问题,测试的发展如何?既然我们的收入又不低,那么干的就得比人家多,你说是不。人家一天接一个客人,咱就得接三个。作为测试的你,是不是有同感?

    (收入跟工作量一定成正比吗?反正我当team member的时候,一直耿耿于怀,我们pm基本上就是陪客户吃吃饭,连C和Java是啥都不知道,完全的关系型的项目经理,人家一个人拿的比我们整个团队都多,这不是更扯淡)

    那么,第二个问题的答案是什么呢?答案就是这篇文章的title,测试团队将慢慢死去!就像《黑天鹅》的作者塔勒布所讲的,这个世界是由一系列不可能发生的事件组成的。测试团队死去这件事情随时可能发生,你要做的,是要提前做好准备!
    (哈哈,这个我喜欢,理论上软件做的多了,就没啥可干的了,所以IBM自己都当投资公司去了,为啥,利润太低,所以啊,指不定那天,软件行业就拉倒了,甭管测试开发需求美工,一起死而已。现在的情形就是这样啊,为什么离岸外包一塌糊涂,就是客户不舍得花钱升级了,旧的能用,要啥新的啊)

    我喜欢描述这样一个场景,一线测试工程师对着电脑在干活儿,左边的高层管理着指着他的鼻子说"别再跟我要head count,我要控制成本!",右边的中层管理着指着他的鼻子说"去给我拓展业务,我要创造业绩!",中间的你,那一脸苦逼的表情,还用我描述吗?

    (哈,这个场景,说实话不太明白,一个测试工程师要去控制成本,去扩展业务,难道公司已经堕落到这种地步?这些东西,跟测试这个role没关系,跟你是负责哪方面的管理有关系,说白了是管理成本而已)

    我认为,测试团队的发展大概要经过这样三个阶段。
    第一阶段,公司快速扩张,不计研发成本,当然测试也不例外,每天都在非常happy的招人中。。。。
    (没计划性?产品开始的时候,连测试计划都没有,你们的测试经理估计是编简历进来的吧,面试的也该拉出去打屁股,连最起码的resource plan都没做,玩个蛋啊,乱堆积木,早晚会塌,不管那个行业)
    第二阶段,经过第一阶段的快速扩张,你的测试团队积累了大量的高级测试工程师,成本已经开始进入高层的考虑范围,技术部开始考虑适度控制成本,而此时,控制最厉害的,肯定是测试团队,当然裁员首先也会从测试团队开始。如果你幸运的没有被裁掉,不要盲目乐观,还有第三阶段。
    (还是那句话,老板太有钱了,没事招一堆高级测试工程师来,最起码的成本cost都没做过预算,看来老板不怕亏本啊)

    第三阶段,(我认为我所在的公司正处于这个阶段)严格控制测试成本,老大们开始考虑将测试工作向上游转移。此时大量的词汇开始进入我们的KPI,什么推动单元测试,推动开发自测,控制提交测试质量,等等,等等。
    讲到这里,今天的关键就出现了,如何将测试的工作向上游转移呢?答案就是第四阶段,让测试团队慢慢死去。。。。
    节省测试成本的最好方式就是把自己干掉!没错!下面我说说方法。
    (哈哈,推动单元测试,推动开发自测,控制提交测试质量...这些说不好听,是process的问题,难道现在还有开发,弄完代码直接往code base里扔,我艹,80年的程序员都知道自测了。好的测试保障,无非是将开发的那些盲目的单元测试合理化而已,user story的出现,就是为了更精确的让所有人有个共同的AC可以依据)

    测试团队当中,首先应该干掉的是纯手工测试工程师,因为他们的性价比是最低的(有些公司这个时候会选择测试外包)。然后,开发测试工程师当中出色的那部分,会加入开发团队当中,不出色的将被淘汰。他们有一项艰巨的任务,那就是,以开发自测为基础,为开发团队建立起一套完整的基于风险的质量控制体系。开发做测试不是能力问题,而是思想,思想却是最难以改变的。这也是好多人天天说要推动开发自测却没有进展的原因,没有认识到改变别人思想的工作有多难!我提的办法呢一石二鸟。开发测试工程师转入开发团队,既能节省测试成本,又可以帮助开发转变思想,以一带二,以一带三,逐步完成开发团队,全民皆测试的目标!

    (首先,干掉什么样的测试人员不依据他们的方式,很多测试本身就是只能纯手工,对于信奉automation可以100%覆盖测试范围的,我只能叹息,你的test scope小,能实现自动化程度高而已,天不是就井口那么大)

    (一般来说,测试没有推动开发的质量提高,这个是PM的问题,甚至是公司文化素质的问题,你能直接教会大字不识的人写出李白那种诗吗,什么事都得一步步来,所以,很多问题根源不是做不做,是做的时候是不是太急功近利了,没错,很多时候建立一个高质量交付团队最多的障碍就是急功近利!没等下鸡蛋,这边油锅就热了)

    (开发测试,本身就应该是在开发范畴中,是为了提供更好的测试做开发,基本上task都是和开发并行的,让开发轮流做开发测试,本身就是个定规啊)

    那么最后,测试团队中还剩什么呢?只会剩测试工具组。他们为全公司提供测试工具,平台和流程方面的支持。极少量的团队会保留纯手工测试工程师。但是,你绝对不应该看到"开发测试工程师"这个title,因为他们已经成为了开发团队中的一员,一起开发,一起测试。。。

    恩,我最讨厌title了,每个人都是不同的role,挂上一个title就不用干别的吗,最起码,一个测试人员,除了测试这个role,还有质量管理这个role,需求人员这个role,文档人员这个role,模拟客户这个role,。。。别提title,sb才觉得自己是什么title就干什么活呢)

    插一段说明,我觉得不必说,但有些人会这么想的。有人会说测试团队应该保留一些测试职位,负责集成测试,系统测试和性能测试。这样说的人很多,但绝对没有过实践经验。为什么呢? 没有与开发天天在一起讨论问题,功能测试这个阶段,怎么能做好集成,系统测试呢? 不要妄想了,这些工作也会由开发团队完成。你可能会觉得开发工程师怎么会做呢? 他们为什么不会做呢?别忘了那些转入开发团队的开发测试工程师有一项艰巨的任务,"以开发自测为基础,为开发团队建立起一套完整的基于风险的质量控制体系",其中就包括测试分工这些在测试团队习以为常的工作。我相信,开发暴发出来的测试能力是你想象不到的。

    (恩,开发的测试能力确实很好的,对代码逻辑足够了解,覆盖率高,但是,自己给自己当监督,早晚权利腐败,尤其是没有文化的项目团队,内部倾轧,都觉得自己代码好,测试的时候随手改别人的代码,测试覆盖面小,考虑的是功能实现,而不是用户体验,说实话,这样的项目做出来客户用起来不爽的例子,那是太多了,12306就是例子,基本上都是开发吧什么集成,系统啊,性能啊做完了,结果呢,出来就是一狗屎,别以为那个单独的开发牛人能一个人把一个团队带到同一个水平,水桶永远是最短的那个木板来决定容量的)

    接下来可能要转换一下角度,站在开发角度来看,他们愿意接受这样一个变化吗?答案是不一定,但只有开发负责人愿意就没问题。我不刻意想学习google,facebook那种模式,但我想说,开发懂测试是一个必然趋势,如果你不想像测试一样被淘汰的话,还是接受吧。
    (很多大的公司,本事是测试覆盖少,很多所有用户都当做免费的测试劳工的,小米的miui就是啊,海量的终端反馈,才是它的测试主体活动)

    测试是一个矛盾体,我们过去,现在,将来一直会做的事情就是让自己死掉(提升开发测试比,开发自测,等等,这些工作我们不是一直在做吗?)。

    (测试不矛盾,矛盾的是测试人员的定位,你的目的不是为了学一个自动化测试工具就是好的测试工程师,什么时候理解项目团队的质量测试体系是全面的质量控制,那就不是一个挂着测试头衔,只会点点点的文档复读机了)

    作为测试的你,能做什么呢?如果你不懂开发,要赶紧去学开发,学设计。如果你懂开发,那就还是要学开发,学设计,技术没有止境。有人跟我说"你过于强调技术,其实测试思想才是最重要的",我认可这种看法,但不完全同意。因为技术能力会束缚你的测试思想,同样也会拓宽你的测试思想。试想都不懂tcp/http协议,怎么测试web server呢? 

    (不错,做好测试,不能只会依据测试文档去覆盖功能,一个好的测试人员,可以当甲方,可以当BA,可以当SA,可以当QA,你需要多方面的知识才行,但是知识是无穷无尽的,所以,知识积累很重要。其实同理也有,你丫不懂java,你怎么给我写个jsp文件出来啊,用C#去写?)

    空谈误国,实干兴邦,牢牢把握技术才是王道!

    (测试技术和开发技术本事是一体的,技术就是技术,没有开发需要学的技术和只有测试需要学的技术,单元测试也是测试范畴啊,你别那纯粹点点点的入门手工测试工程师,又是title,来代表整个测试水平,就跟没人拿一个刚学了三天java的开发去代表开发的整体水品一个道理)


    上面这篇文章是前阶段淘宝前辈邓悟写的,感觉有一定道理,就拿过来跟大家分享下(已得到前辈同意);关于测试团队的前三个阶段发展的论述比较赞同,感觉现在好多大公司的确也有这种趋势;
    (说实话,什么叫大,外包这种纯粹堆人头的叫大?还是那些动不动拿自己当50强的it公司觉得自己大,摩托罗拉为啥没落了,那么大的公司,已经不是技术范畴内的问题了,是人的恶性导致的,就是窝里斗,甭管那个国家,人类窝里斗那是人类史的源动力,人就是地球的寄生虫)
    对于第四个阶段不发表评论,感觉测试职位只是一种合理分工的产物,如果这种分工方式对于公司来说成本相对较低,公司当然会保留;
    (对职位是职位,职责是职责,对于很多混日子的人民公仆也同样道理,只不过,公司老板烦了能开人,我们当家做主的烦了只能自己在家画圈圈。)

    对于前辈说的这种可能对于国内大多数公司感觉暂时不太可能(未来就不做猜测了),当然像淘宝这样的公司要另说;对于前辈说的“技术”,我的看法也是多多益善,但是人的精力毕竟有限,要结合实际工作做取舍。

    (没有哪个公司能逃过这种社会悲剧的,天下没有不散的筵席,没有不倒闭的公司,与制度有关,与技术无关,技术宅才是希望,瓦咔咔)
    原文链接:http://blog.sina.com.cn/s/blog_71ad0d3f0101bytk.html
  • Ruby语言入门(16)- 内部类 -IO

    2013-02-04 16:29:26

    IO类实现了基本的输出输入功能。

    IO.new(fd[, mode])
    IO.for_fd(fd[, mode]) 
    IO.open(fd[, mode]) 
    IO.open(fd[, mode]) {|io| ... } 
    生成并返回一个全新的IO对象,它对应于已打开的文件描述符fd。

    IO.for_fd与IO.new相同。IO.open稍有不同,因为它可以带块(块运行结束时fd会被关闭)。带块的IO.open返回块的结果。其他的返回生成的IO对象。

    IO.foreach(path[, rs]) {|line| ... }
    对path所指文件的各行内容进行迭代操作(与open一样,若path以"|"开头的话则读取命令输出)。


    IO.pipe
    执行pipe(2)后返回一个数组,该数组包括2个互联的IO对象。返回数组中的首元素负责读取,第二个元素负责读入。

    pipe = IO.pipe    
    => [#<IO:fd 3>, #<IO:fd 4>]
    pipe[1].puts "test"
    pipe[0].gets      
    => "test\n"

    IO.popen(command [, mode])
    IO.popen(command [, mode]) {|io| ... }
    将command作为子进程来运行,然后建立一条连接到该进程的输入输出的管线(pipeline)。

    io = IO.popen("cat", "r+")  
    => #<IO:fd 7>
    io.puts "test"
    io.gets  
    => "test\n"

    若带块时,将以生成的IO对象为参数来运行该块,并返回其结果。在块得到运行以后,生成的管道将会自动关闭。

    IO.popen("cat", "r+") {|io|
      io.puts "test"
      io.gets
    }
    => "test\n"

    当命令名为"-"时,Ruby将运行fork(2)来建立一个连接到子进程的输入输出的管线。

    不带块的例子

    io = IO.popen("-", "r+")
    if io.nil?
      # child
      s = gets
      print "child output: " + s
      exit
    end

    # parent
    io.puts "test"
    puts io.gets                   
    => "child output: test\n"
    io.close

    带块的例子

    p IO.popen("-", "r+") {|io|
      if io
        # parent
        io.puts "test"
        io.gets
      else
        # child
        s = gets
        puts "child output: " + s
      end
    }
    => "child output: test\n"

    IO.read(path,[length,[offset]]) 
    在path所指文件中,从offset位置开始读入length字节的内容并将其返回。

    IO.read("c:\\test.txt")
    =>"test1\ntest2\ntest3\n"

    IO.readlines(path[, rs])
    读入path所指文件的全部内容后,以行为单位将其转化为数组并返回该数组。

    IO.readlines("c:\\test.txt")
    =>["test1\n","test2\n","test3\n"]

    IO.select(reads[, writes[, excepts[, timeout]]])
    执行select(2)。传递给reads/writes/excepts的是等待输入的IO(或其子类)的实例的数组。


    IO.sysopen(path[, mode [, perm]]) 
    打开path所指文件并返回文件描述符。

    newfile = IO.systemopen("c:\\test.txt","r+")
    =>3
    newff = IO.new(newfile)
    =>#<IO:fd 4>

    self << object
    输出object。可以像下面这样使用一连串的<<:

    newfile = IO.systemopen("c:\\test.txt")
    =>3
    newff = IO.new(newfile, "a+")
    =>#<IO:fd 4>
    newff <<1<<"test"<<"\n"

    binmode
    将流变为二进制模式。

    new1 = newff.binmode

    clone
    dup
    返回一个全新的IO对象,该对象与receiver使用同一个IO

    new2 = newff.clone

    close
    关闭输入输出端口。

    new2.close


    close_read
    关闭读取用的IO。主要用在管道或读写两用的IO对象上。

    new2.close_read

    close_write
    关闭写入用的IO。

    new2.close_write

    closed?
    若端口已被关闭则返回真。

    new.closed?

    each([rs]) {|line| ... }
    each_line([rs]) {|line| ... }
    每次从IO端口读入1行来进行相关处理的迭代器。

    each_byte {|ch| ... }
    每次从IO端口读入1字节的内容。

    eof
    eof?
    若流(stream)到达文件末端时返回真.

    fcntl(cmd[, arg])
    将对IO执行系统调用fcntl(2)。

    fsync
    对写入用的IO执行系统调用fsync(2).

    fileno
    to_i
    返回文件描述符的号码。

    newfile.fileno
    =>2

    flush
    刷新IO端口的内部缓冲区。 

    newfile.flush

    getc
    从IO端口读入1个字符,并返回该字符对应的Fixnum。

    gets([rs])
    读入一行,若成功的话就返回读入的字符串。

    ioctl(cmd[, arg])
    对IO执行系统调用ioctl,并返回其结果。

    isatty
    tty?
    若输出输入端口已与tty结合时,返回真。

    lineno
    返回当前的行号。

    lineno=number
    设定行号。

    pid
    若是由IO.popen所生成的IO端口时,则返回子进程的进程ID。除此以外返回nil。

    pos
    tell
    返回文件指针的当前位置。

    pos = n
    将文件指针移动到指定位置。与io.seek(pos, IO::SEEK_SET)相同。

    print([arg[, ...]])
    依次将参数输出到IO端口。

    printf(format[, arg[, ...]])
    按照format将参数变为字符串,然后输出到self。

    putc(ch)
    输出字符ch到self。

    puts([obj[, ...]])
    输出各个obj到self然后换行。

    read([length])
    read([length[, buf]])
    若给出了length时,就读取length字节的内容,然后返回该字符串。

    若将某字符串传给第二参数的话,将使用读入的数据来覆盖该字符串对象,并返回读入的数据。

    buf="x"*20
    =>"xxxxxxxxxxxxxxxxxxxxx"
    io=File.open("c:\\test.txt")
    io.read(10,buf)
    buf
    =>"test"

    readchar
    与IO#getc一样,读入1个字符后返回与该字符相对应的Fixnum。

    readline([rs])
    与IO#gets一样,读入1行后返回读入的字符串.使

    readlines([rs])
    读入所有数据后,以行为单位将其转化为数组,并返回该数组。

    readpartial(maxlen[, outbuf])
    从IO读入最多maxlen的数据,并返回读入的字符串。

    reopen(io)
    reopen(name[, mode])
    将自身转接到io上.若第一参数为字符串时,将把流转接到name所指的文件上。第二参数的默认值为"r"。若省略第二参数时,将原封不动地继承self的模式。

    rewind
    将文件指针移动到头部。IO#lineno变为 0 。

    seek(offset[, whence])
    将文件指针由whence移动到offset。whence的值是下列之一。
    • IO::SEEK_SET: 从文件头部开始(默认)
    • IO::SEEK_CUR: 从当前文件指针开始
    • IO::SEEK_END: 从文件尾部开始
    • 省略whence时,其默认值为IO::SEEK_SET。

    stat
    生成并返回一个包含文件状态的File::Stat对象。

    sync
    以真和伪来表示当前的输出同步模式。当输出同步模式为真时,每次调用输出函数时都会刷新缓冲区。

    sync=newstate
    设定输出同步模式。newstate为真则表示同步模式,伪则表示非同步模式。

    sysread(length)
    sysread(length[, buf]) 
    使用read(2)进行输入,并返回包含输入数据的字符串.

    sysseek(offset[, whence]) 
    与lseek(2)相同

    yswrite(string)
    使用write(2)来输出string。若string并非字符串,将使用to_s尝试将其变为字符串。

    to_io
    返回self。

    ungetc(char)
    送回(unreading)char

    write(str)
    对IO端口输出str。若str并非字符串,将使用to_s尝试将其变为字符串。

    常数:
    SEEK_CUR
    SEEK_END
    SEEK_SET

    newfile.SEEK_CUR
    newfile.SEEK_END
    newfile.SEEK_SET
  • Ruby语言入门(15)- 内部类 -Hash

    2013-02-04 15:12:48

    哈希表(也叫散列表)的类.通过哈希表,您可以将一个任意类型的对象同另一个任意类型的对象联系起来.

    可以使用下列哈希表表达式来生成哈希表: {a=>b, ... } (key=>value)

    通常使用Object#hash方法来计算哈希表的值,而使用Object#eql?方法来判定索引是否相同.

    Hash[key,value,...]
    Hash[hash]
    生成新的哈希表.使用第一种形式时,参数的个数必须是偶数.(奇数位参数是索引,偶数位参数是元素值).使用第二种形式(将一个哈希表对象指定给参数)时, 将生成并返回一个与指定哈希表相同的全新的哈希表.(生成的哈希表的默认值为nil.)

    以下是从数组生成哈希表的方法示例:

    由[索引, 值, ...] 型的数组变为哈希表
    ary = [1,"a", 2,"b", 3,"c"]
    puts Hash[*ary]
    => {1=>"a", 2=>"b", 3=>"c"}
    puts Hash[ary]
    =>{}

    由索引和值配对出现的数组变为哈希表
    alist = [[1,"a"], [2,"b"], [3,"c"]]
    puts Hash[*alist.flatten]
    => {1=>"a", 2=>"b", 3=>"c"}

    由索引数组和值数组配对生成哈希表
    keys = [1, 2, 3]
    vals = ["a", "b", "c"]
    alist = keys.zip(vals)   # 或 alist = [keys,vals].transpose
    puts Hash[*alist.flatten]
    => {1=>"a", 2=>"b", 3=>"c"}

    无法使用上述的方法时:
    h = Hash.new
    alist = [[1,["a"]], [2,["b"]], [3,["c"]]]
    alist.each {|k,v|
      h[k] = v
    }
    puts h
    => {1=>["a"], 2=>["b"], 3=>["c"]}

    Hash.new([ifnone])
    Hash.new {|hash, key| ...} 
    生成一个全新的空哈希表.若索引没有对应值时,其默认值为ifnone.若指定了块时,则块的计算值将成为默认值.每当调用无值的哈希表元素时,都会对块进行计算,然后返回其结果.而调用哈希表时的索引将被传递给该块.

    若没有使用块时, 改变默认值将会影响到其他的值
    h = Hash.new("foo")
    puts h[1]                  # => "foo"
    puts h[1] << "bar"         # => "foobar"
    puts h[1]                  # => "foobar"
    puts h[2]                  # => "foobar"

    若使用块的话,不会出现这种问题
    h = Hash.new {|hash, key| hash[key] = "foo"}
    puts h[1]                  # => "foo"
    puts h[1] << "bar"         # => "foobar"
    puts h[1]                  # => "foobar"
    puts h[2]                  # => "foo"

    self[key]
    返回索引为key的哈希表元素的值.若该索引并未注册,则返回默认值(若未设定则为nil).若想区分该nil到底是默认值还是哈希表元素值时,请使用fetch.

    h = Hash.new {|hash, key| hash[key] = "foo"}
    puts h[1]
    =>"foo"

    self[key]=value
    store(key,value)
    将索引为key的元素值设为value.返回value.

    h[2]="fool"
    h[2]
    =>"fool"
    h.store(3,"test")
    h[3]
    =>"test"

    clear
    清空哈希表的内容. 返回self.

    h.clear
    =>{}

    clone
    dup
    返回一个与receiver内容一致的新哈希表. 对冻结的哈希表进行clone时将返回一个同样的冻结的哈希表.但使用dup时,将返回内容相同但却并未冻结的哈希表.

    b=h.clone
    b[1]
    =>"foo"

    default
    default([key])
    返回哈希表的默认值.

    h.default
    =>nil
    h.default("123")
    =>foo
    h("123")
    ="foo"

    default=value
    将哈希表的默认值设为value.若使用无对应值的索引进行搜索时,将返回该值.

    h.default="test"
    h.default
    =>"test"
    h[10]
    =>"test"

    default_proc
    返回一个Proc对象,该对象负责返回哈希表的默认值.若没有默认的Proc时将返回nil.

    h = Hash.new {|h, k| }
    puts h.default_proc        
    => #<Proc:0x0x401a9ff4>

    h = Hash.new(1)
    puts h.default_proc        
    => nil

    delete(key)
    delete(key) {|key| ... }
    删除索引key与对应元素之间的关系.返回被删除的值.若没有值与key相对应,则返回nil.若给出块的话,将在key匹配失败时对块进行计算,然后返回其结果.

    h
    => {1=>"test",2="test",3=>"test"}
    h.delete(2)
    h
    => {1=>"test",3=>"test"}

    reject {|key, value| ... }
    拷贝self之后对块进行计算,若计算值为真则删除相应的哈希表元素,最后返回该哈希表.

    delete_if {|key, value| ... }
    reject! {|key, value| ... }
    把key和value当做参数来计算块,若计算值为真则删除相应的元素.通常delete_if返回self. reject!就有所不同,若未删除元素时返回nil,除此之外则返回self.


    each {|key, value| ... }
    each_pair {|key, value| ... }
    以key和value为参数对块进行计算.返回self.

    {:a=>1, :b=>2}.each_pair {|k, v| puts [k, v]}

    => [:a, 1]
       [:b, 2]

    each_key {|key| ... }
    以key为参数来计算块.返回self.

    each_value {|value| ... }
    以value为参数来计算块.返回self.

    empty?
    若哈希表为空则返回真.

    fetch(key[, default])
    fetch(key) {|key| ... }
    返回与索引key对应的元素的值.若该索引未被注册则分为两种情况: 若给出了参数default的话,就返回它的值;若给出了块时,将返回块的计算值

    has_key?(key)
    include?(key)
    key?(key)
    member?(key)
    若key是哈希表的索引则返回真.

    has_value?(value)
    value?(value)
    若value是哈希表的元素值则返回真.对值进行判断时使用==操作符

    index(val)
    返回与val对应的索引.若无法对应时返回nil.若有若干个对应的索引时,则会随机地返回其中之一.

    invert
    将元素值和索引互换,返回变换后的哈希表.
    h = { "n" => 100, "m" => 100, "y" => 300, "d" => 200, "a" => 0 }
    h.invert
    => {200=>"d", 300=>"y", 0=>"a", 100=>"n"}

    keys
    返回一个包含所有索引的数组.

    length
    size
    返回哈希表中的元素的个数.

    merge(other)
    merge(other) {|key, self_val, other_val| ... }
    merge!(other)
    merge!(other) {|key, self_val, other_val| ... }
    合并两个hash表。当self和other中包含相同索引时将按照下列两种方式来处理: 若带块则调用该块,然后由用户选择使用哪个值;不带块的话则通常使用other的值.

    rehash
    重新计算索引对应的哈希表值。当与索引对应的哈希表值发生变化时,若不使用该方法来重新计算的话,将无法取出与索引对应的哈希表值。

    replace(other)
    以other的内容来替换哈希表的内容。返回self。

    shift
    删除一个哈希表元素后,再以[key,value]数组的形式将其返回。

    to_a
    生成并返回一个数组,数组中的元素也是数组,且由[key,value]构成。

    to_hash
    返回self。

    update(other)
    update(other) {|key, self_val, other_val| ... } 
    合并哈希表的内容。若出现相同索引时,将使用other中对应的元素值。若给出了块的话,每当遇到相同索引时都会对块进行计算,然后以块的计算值作为该索引的对应值。此时,索引、self[key] 和other[key]将被作为参数传递给该块。

    foo = {1 => 'a', 2 => 'b', 3 => 'c'}
    bar = {1 => 'A', 2 => 'B', 3 => 'C'}
    p foo.dup.update(bar)                   
    => {1=>"A", 2=>"B", 3=>"C"}
    p foo.dup.update(bar) {|k,v| v}         
    => {1=>"a", 2=>"b", 3=>"c"}

    values
    返回一个包括哈希表中的所有元素值的数组。

    values_at(key_1, ... , key_n)
    返回一个数组,该数组包括与参数所指索引相对应的哈希表元素值。若没有与索引相对应的哈希表元素值时,将使用default的值。与indexes以及indices相同。


  • Ruby语言入门(14)- 内部类 -File::Stat

    2013-02-04 14:40:16

    File::Stat 是保存文件信息的对象的类.

    生成方法:

    File::Stat.new(path)
    生成并返回一个关于path的File::Stat对象. 

    afile=File::Stat.new("c:\\test.jpg")
    => $<Fiel::Stat dev=0x2.........+0800>

    File::Stat
    生成并返回一个File::Stat对象. 

    bfile=File::Stat
    =>File::Stat
    cfile=b.new("c:\\test.jpg")
    => $<Fiel::Stat dev=0x2.........+0800>

    self <=> other
    比较文件的最终更新时间.若self比other新就返回正数,相等就返回0,旧则返回负数.

    afile<=>cfile
    =>0

    ftype
    返回一个表示文件类型的字符串.该字符串应是下列之一:
    • "file"
    • "directory"
    • "characterSpecial"
    • "blockSpecial"
    • "fifo"
    • "link"
    • "socket"
    • "unknown"
    afile.ftype
    =>"file"

    dev
    设备号(文件系统)

    afile.dev
    =>2

    dev_major
    dev的major号码部分

    afile.dev_major
    =>nil

    dev_minor 
    dev的minor号码部分

    afile.dev_minor
    =>nil

    ino
    i-node 号

    afile.ino
    =>0

    mode
    文件模式

    afile.mode
    =>33188

    nlink
    hard link数

    afile.nlink
    =>1

    uid
    owner的userID

    afile.uid
    =>0

    gid
    owner的groupID

    afile.gid
    =>0

    rdev
    设备类型

    afile.rdev
    =>2

    rdev_major
    rdev的major号码部分

    afile.rdev_major
    =>nil

    rdev_minor
    rdev的minor号码部分

    afile.rdev_minor
    =>nil

    size
    文件大小(以字节为单位)

    afile.size
    =>25780

    blksize
    理想的I/O的块大小

    afile.blksize
    =>nil

    blocks
    被分配的块数

    afile.blocks
    =>nil

    atime
    最终访问时间

    afile.atime
    =>2013-02-04 14:17:43 +0800

    mtime
    最终更新时间

    afile.atime
    =>2013-01-21 16:07:43 +0800

    ctime
    最终i-node变更时间

    afile.ctime
    =>2013-01-21 16:07:43 +0800


    下列判断方法等同于那些与FileTest同名的模块函数. 虽然它们的参数中使用的是文件名,但却对Stat本身进行判断.

    directory?
    若为目录则为真

    afile.directory?
    =>false

    readable?
    若可读则为真

    afile.readable?
    =>true

    readable_real?
    若实用户/实组可以读取就为真

    afile.readable_real?
    =>true

    writable?
    若可写则返回真

    afile.writable?
    =>true

    writable_real?
    若实用户/实组可以写入就为真

    afile.writable?
    =>true

    executable?
    若有效用户/组ID能执行就为真

    afile.executable?
    =>false

    executable_real?
    若实用户/组ID能执行就为真

    afile.executable_real?
    =>false

    file?
    若为普通文件则返回真

    afile.file?
    =>true

    zero?
    若大小为0就为真

    afile.file?
    =>false

    size?
    文件大小(若为0则为伪)

    afile.size?
    =>25780

    owned?
    若属于自己则为真

    afile.owned?
    =>true

    grpowned?
    若组ID与执行组ID相等则为真

    afile.grpowned?
    =>false

    pipe?
    若是带名称管道(FIFO)则为真

    afile.pipe?
    =>false

    symlink?
    若是符号连接则为真

    afile.symlink?
    =>false

    socket?
    若是socket则为真

    afile.socket?
    =>false

    blockdev?
    若是块专用文件则为真

    afile.blockdev?
    =>false

    chardev?
    若是字符专用文件则为真

    afile.chardev?
    =>false

    setuid?
    若被setuid则为真

    afile.setuid?
    =>false

    setgid?
    若被setgid则为真

    afile.setgid?
    =>false

    sticky?
    若设定了粘着位(sticky bit)则为真

    afile.sticky?
    =>false
  • Ruby语言入门(13)- 内部类 -Dir

    2013-02-04 13:25:26

    Dir类为实现目录流操作而设置的类,它可以依次返回目录中的元素。

    Dir[pattern]
    Dir.glob(pattern)
    Dir.glob(pattern) {|file| ...}
    Dir.glob(pattern[, flags]) 
    Dir.glob(pattern[, flags]) {|file| ...} 
    以字符串数组的形式返回通配符匹配结果。若指定了块的话,将以匹配成功的文件为参数,依次计算该块,然后返回nil。可以一次指定多个pattern,此时需要使用空白(space,tab,换行)或"\0"将它们分割开来。

    可用的通配符(pattern)如下。
    • * 匹配任何字符串,包括空字符串。
    • ? 匹配任何一个字符。
    • [ ] 只要匹配方括号中任何一个字符即可。若使用-则表示字符范围。若方括号中的首字符是^时,表示匹配^后的字符以外的任意字符。
    • { } 表示依次与括号内的字符进行组合。例如,foo{a,b,c}将变为fooa, foob, fooc,然后再依次进行匹配。括号可以嵌套。例如,{foo,bar{foo,bar}}表示将依次与foo, barfoo, barbar进行匹配。
    • **/ 表示通配符*/重复出现0次以上,这将对目录进行再归式地搜索。例如,foo/**/bar表示将依次对foo/bar, foo/*/bar, foo/*/*/bar ... (此后无限延伸)进行匹配。
    • 可使用反斜线对通配符进行转义处理。
    • 可以为第2可选参数指定一个类似于File.fnmatch中所使用的标识。
    Dir.getwd
    Dir.pwd
    返回当前目录的完整路径。

    Dir.chdir([path])
    Dir.chdir([path]) {|path| ... } 
    将当前目录改为path。若省略path时,则会调用环境变量HOME或LOGDIR。若它们中包含设定值时,就将当前目录改为它们的值。若当前目录变更成功就返回0,若失败则引发Errno::EXXX异常。若指定了块的话,则只会在块的执行过程中变更当前目录。

    Dir.pwd
    =>"c:/"
    Dir.chdir("c:\\Sites")
    =>0
    Dir.pwd
    =>"c:/Sites"


    Dir.chroot(path)
    将根目录改为path。只有超级用户才能改变根目录。您将无法还原到原来的根目录。根目录变更成功时返回0,失败时将引发Errno::EXXX异常。

    Dir.mkdir(path[, mode])
    生成新目录path.若成功生成新目录就返回0,若失败则引发Errno::EXXX异常。

    Dir.mkdir("c:\\test")
    =>0

    Dir.delete(path)
    Dir.rmdir(path)
    Dir.unlink(path)
    删除目录。目录必须为空。若删除成功则返回0,若失败则引发Errno::EXXX异常。

    Dir.delete("c:\\test")
    =>0

    Dir.entries(path)
    以数组形式返回path目录中所含的文件项名

    Dir.entries("c:\\Sites")
    =>[".", "..", "chromedriver.log", "todo"]

    Dir.foreach(path) {|file| ...}
    针对path目录中的元素的迭代器。

    Dir.new(path)
    Dir.open(path)
    Dir.open(path) {|dir| ...}
    打开并返回一个针对path的目录流。若打开失败则引发Errno::EXXX异常。open()方法可以带块。若带块调用时,将执行该块。当块的运行结束时,目录将被自动关闭。

    a=Dir.open("c:\\Sites")
    => #<Dir:c:\Sites>

    close
    关闭目录流。此后若再对目录进行操作则会引发IOError异常。若成功关闭则返回nil。若失败则引发IOError异常。

    a.close
    =>nil
    a.tell
    IOError: closed directory

    each {|item| ... }
    为目录中的各个元素计算块的内容。返回self。

    a.each {|item| puts item}
    .
    ..
    chromedriver.log
    todo
    => #<Dir:c:\Sites>

    path
    以字符串形式返回当前打开目录的路径名。

    a.path
    =>"c:\\Sites"

    pos
    tell
    以整数形式返回目录流的当前位置。

    a.pos
    =>4

    pos=(pos)
    seek(pos)
    将目录流的读入位置移动到pos。pos必须是使用Dir#tell所得到值。pos=返回右边,而seek则返回self。

    a.seek(2)
    => #<Dir:c:\Sites>
    a.tell
    => 2

    read
    从目录流中读出并返回下一个元素。若读到最后一个元素则返回nil。若读取目录失败则引发Errno::EXXX异常。

    a.read
    =>"chromedriver.log"

    rewind
    将目录流的读取位置移到开头。返回self。

    a.rewind
    => #<Dir:c:\Sites>
    a.tell
    =>0
  • Ruby语言入门(12)- 内部类 - Array

    2013-02-01 15:54:37

    数组的元素可以是任意的Ruby对象。包含的模块:Enumerable

    类生成方法有:

    Array[item,...]

    a=Array[1,2,3]
    =>[1,2,3]

    Array.new([size[, val]])

    a=Array.new(5,1)
    =>[1,1,1,1,1]

    Array.new(ary)

    b=Array.new(a)
    =>[1,1,1,1,1]
    a==b
    =>true

    Array.new(size) {|index| ... }

    a=Array.new(3){"test"}
    =>["test","test","test"]

    类的内置方法有:

    self[nth]
    返回第nth个数组元素。首元素算做第0个元素。若nth值为负,则看作是从尾部算起的索引值(尾元素算做第-1个元素)。若第nth个元素不存在,则返回nil。

    a=Array[1,2,3]
    a[1]
    =>2
    a[-1]
    =>3

    self[start..end]
    以数组形式返回从第start个元素到第end个元素间的所有元素。若start值为负,则看作是从尾部算起的索引值(尾元素算做第-1个元素)。若start的值超出数组范围则返回nil。若end的值超出数组长度时,超出的部分将被忽略。另外,若范围的起点比终点还大时,返回nil。

    a=Array[1,2,3]
    a[1..10]
    =>[2,3]
    a[-1..3]
    =>[3]

    self[start, length]
    以数组形式返回从第start个元素算起的length个数组元素。若start值为负,则看作是从尾部算起的索引值(尾元素算做第-1个元素)。若length超出从第start个元素算起的剩余长度时,超过部分将被忽略。若length为负,则返回nil。

    a=Array[1,2,3]
    a[1,4]
    =>[2,3]
    a[-1,2]
    =>[3]

    self[nth]=val
    将第nth个数组元素的值设定为val。若nth超出数组范围时,将自动加长数组并以nil对新增部分进行初始化。

    a=Array[1,2,3]
    a[6]=6
    a
    =>[1,2,3,nil,nil,6]

    self[start..end]=val
    将从第start个数组元素到第end个数组元素间的所有元素替换为val的内容。若val并非数组时,则就以val进行替换。若val的元素个数过多时,后面的元素将会发生移位。若val为nil或空数组[]时,将删除从start到end的元素。

    a=Array[1,2,3]
    a[1..3]=["a","b"]
    a
    =>[1,"a", "b"]
    a[1..3]=6
    a
    =>[1,6]

    a=[0, 1, 2, 3, 4, 5]
    a[0..2]=["a", "b"]
    a
    => ["a", "b", 3, 4, 5]

    a[2..4] = nil
    a
    => ["a", "b"]

    self[start, length]=val
    将从索引start算起的length个数组元素替换为val的内容。若val不是数组时,则调用val.to_ary或使用[val]进行替换。返回val。

    a=Array[1,2,3]
    a[1,3]=["a","b"]
    a
    =>[1,"a", "b"]
    a[1,3]=6
    a
    =>[1,6]


    a=[0, 1, 2, 3]
    a[1, 2]=['a', 'b', 'c']
    a                      
    => [0, "a", "b", "c", 3]
    a[2, 1] = 99
    a                        
    => [0, "a", 99, "c", 3]
    a[1, 0] = ['inserted']
    a
    => [0, "inserted", "a", 99, "c", 3]


    self + other
    将self和other的内容连起来后生成新数组并返回该数组。若other并非数组时则使用other.to_ary的返回值。若该返回值依然不是数组时,则引发TypeError异常。

    a=[1,2]
    b=[3,4]
    a+b
    =>[1,2,3,4]

    self * times
    将数组内容重复多次后生成一个新数组并返回该数组.

    a=[1, 2, 3] 
    a*3  
    => [1, 2, 3, 1, 2, 3, 1, 2, 3]

    若times为字符串,则其动作等同于self.join(times)。
    a*"a"
    =>"1a2a3a"

    self - other
    集合的补集运算。从self中删除other的元素后生成一个新数组并返回该数组。重复元素将被清除。

    a=[1, 2, 3] 
    a-[1]
    => [2, 3]

    self & other
    集合的交集运算。将同属于两个数组的元素重组为一个新数组并返回该数组。重复元素将被清除。

    a=[1, 2, 3]
    b=[1, 4, 5] 
    a&b
    => [1]

    self | other
    集合的并集运算。将任属两数组之一的元素重组为一个新数组并返回该数组。重复元素将被清除。

    a=[1, 2, 3]
    b=[1, 4, 5] 
    a|b
    => [1,2,3,4,5]

    self << obj
    将obj追加到数组尾部。

    a=[1, 2, 3]
    a<<5
    => [1,2,3,5]
    a<<5<<6<<7
    =>[1,2,3,5,5,6,7]

    self <=> other
    使用<=>来依次比较self和other中的各个元素。若self大则返回正整数;若相等返回0;若小则返回负整数。如果各个元素均相等,且其中一个数组已到达尾部时,则认定较短的数组为小。

    self = = other
    使用==来依次比较self和other中的各个元素,若所有元素均相等时返回真。


    assoc(key)
    对数组中的元素数组进行检索,若某元素数组的首元素与key相等时就返回该元素数组。使用==操作符进行比较。若没有符合条件的元素数组就返回nil。

    a = [[1,15], [2,25], [3,35]]
    a.assoc(2)           
    => [2, 25]
    a.assoc(15)
    =>nil

    at(pos)
    返回位于pos的数组元素。与self[pos]相同。

    a = [[1,15], [2,25], [3,35]]
    a.at(2)           
    => [3, 35]
    a[2]
    => [3, 35]

    clear
    删除数组中的所有元素。返回self。

    clone/dup
    生成一个与receiver内容一样的新数组并返回它。clone会拷贝frozen tainted singleton-class等信息,而dup则只拷贝内容。

    collect! {|item| ..} / map! {|item| ..}
    依次将数组的各个元素传给块进行计算,然后以计算结果来替换该数组元素

    a = [1, 2, 3]
    aa.map! {|i| i * 3 }
    a   
    => [3, 6, 9]

    compact/compact!
    compact从self中删除值为nil的元素后生成新数组并返回它。compact!是具有破坏性的,若对原数组进行了改动就返回self,若没有进行改动则返回nil。

    a = [1, nil, 2, nil, 3, nil]
    a.compact!   
    a
    => [1, 2, 3]

    concat(other)
    将other连接到self末尾(该动作具有破坏性)。返回self。

    a=[1,2]
    b=[3,4]
    a.concat(b)
    a
    =>[1,2,3,4]

    delete(val)/delete(val) { ... }
    使用==来分别比较val与每个数组元素,若相等则删除该元素。若发现了与val相等的元素就返回val。若没有发现与val相等的元素则返回nil,若指定了块的话就对块进行计算并返回结果。

    array = [1, 2, 3, 2, 1]
    array.delete(2) 
    array                 
    => [1, 3, 1]


    delete_at(pos)
    删除pos所指位置的元素并返回它。若pos超出数组范围则返回nil。与at一样,可以使用负的索引从尾部起指定.

    array = [0, 1, 2, 3, 4]
    array.delete_at(2)
    array             
    => [0, 1, 3, 4]

    delete_if {|x| ... }
    reject! {|x| ... }
    依次将元素传给块进行计算,若结果为真就删除相应元素。delete_if通常返回self。若没有删除任何元素时,reject!会返回nil。

    a=[1,2,3]
    a.delete_if{|x|x=false}
    =>[1,2,3]
    a.delete_if{|x|x=true}
    =>[]

    each {|item| .... }
    依次使用每个元素来计算块。返回self。

    a=[1, 2, 3]
    a.each{|i|puts i}
    1
    2
    3
    =>[1,2,3]

    each_index {|index| .... }
    依次使用每个元素的索引来对块进行计算

    a=[1, 2, 3]
    a.each_index{|i|puts i}
    1
    2
    3
    =>[1,2,3]

    empty?
    若数组元素数目为0则返回真。

    eql?(other)
    使用Object#eql?来依次计算self和other的各个元素,若所有元素均相等则返回真。


    fetch(nth) 
    fetch(nth, ifnone)
    fetch(nth) {|nth| ... }
    与Array#[nth]一样,返回第nth个元素。但若没有第nth个元素的话,它的运作就有别于Array#[nth]了:第一种形式会引发IndexError异常。第二种形式会返回参数ifnone。而第三种形式会返回块的计算结果。

    a=[1, 2, 3]
    a.fetch(1)
    =>2

    fill(val)
    fill(val, start[, length])
    fill(val, start..end)
    fill {|index| ... } 
    fill(start[, length]) {|index| ... }
    fill(start..end) {|index| ... } 
    将val赋值给数组中被指定的范围内的所有元素。在第二种形式中,若省略length则意味着将指定范围扩大到数组尾部。若指定范围最终超出原数组的长度时,将自动加长原数组,并以val来对新增元素进行初始化。

    a=[1, 2, 3]
    a.fill(1)
    =>[1,1,1]

    first/first(n) 
    返回数组的首元素。若没有首元素则返回nil。
    a=[1, 2, 3]
    a.first
    =>1
    a.first(2)
    =>[1,2]

    flatten/flatten!
    将带嵌套的数组重整为不带嵌套的单纯数组,并返回它。flatten!的重整具有破环性,若原数组不带嵌套则返回nil。

    a=[1, [2, 3, [4], 5]]
    a.flatten   
    => [1, 2, 3, 4, 5]

    include?(val)
    若数组中包含==val的元素就返回真。

    index(val)
    返回数组中第一个==val的元素的位置。若没有与其相等的元素则返回nil。
    a=[1, 2, 3]
    a.index(1)
    =>0

    insert(nth, val[, val2 ...])/insert(nth, [val[, val2 ...]])
    在索引为nth的元素前面插入第2参数以后的值。返回self。

    a=[1, 2, 3]
    a.insert(2,'a','b')
    =>[1,2,"a","b",3]

    join([sep])
    将sep字符串夹在各元素中间使数组转换为字符串,并返回该字符串。

    若数组元素并非字符串的话,就调用to_s然后再进行连接。若元素依然是数组时,将再归调用(同样适用sep)join来连接字符串。
    若sep为nil则使用空字符串。
    若参数sep被省略,则使用变量$,的值。$,的默认值为nil。

    a = [1,2,3]
    ary.join("a")    
    => "1a2a3"

    last/last(n) 
    返回数组末尾的元素。若数组为空时,返回nil。

    a=[1, 2, 3]
    a.last
    =>3
    a.lasst(2)
    =>[2,3]

    length/size
    返回数组长度。若数组为空则返回0.

    a=[1, 2, 3]
    a.length
    =>3
    a.size
    =>3

    nitems
    返回非nil元素的个数

    pack(template)
    按照template所指字符串的样式,以二进制的形式将数组的内容打包成字符串,并返回该字符串

    pop
    删除末尾元素并返回它。若数组为空则返回nil。

    a=[1, 2, 3]
    a.pop
    =>[1,2]

    push(obj1[, obj2 ...])/push([obj1[, obj2 ...]]) 
    依次将obj1, obj2 ...添加到数组结尾。

    array = [1, 2, 3]
    array.push(4)
    =>[1,2,3,4]

    rassoc(obj)
    假定self是数组中的元素数组,若首次发现元素数组中索引为1的元素与obj相等时就返回该元素。使用==操作符进行比较。若没有符合条件的元素数组则返回nil。

    a = [[15,1], [25,2], [35,3]]
    a.rassoc(2)    
    => [25, 2]

    replace(another)
    以数组another来替换该数组的内容。返回self。

    a = [1, 2, 3]
    a.replace([4, 5])
    =>[4,5]

    reverse/reverse!
    reverse将所有元素以逆序重新排列生成新数组并返回它。reverse!的逆序排列过程具有破环性。reverse通常返回新数组。若数组只有1个元素,reverse!会返回nil,除此以外将返回self。

    a = [1, 2, 3]
    a.reverse
    =>[3,2,1]

    reverse_each {|item| ... }
    对各个元素以逆序对块进行计算。返回self。

    rindex(val)
    返回最后一个== val的元素的索引值。若没有符合条件的元素时返回nil。

    p [1, 0, 0, 1, 0].rindex(1)   
    => 3

    shift
    删除数组的首元素并返回它。剩余元素依次提前。若数组为空返回nil。

    slice(pos[, len])/slice(start..last)
    与self[]相同。

    slice!(pos[, len])/slice!(start..last)
    删除指定的元素并返回它。若没有可删除的元素时返回nil。

    sort
    sort!
    sort {|a, b| ... }
    sort! {|a, b| ... }
    对数组内容进行排序。若带块调用时,将把2个参数传给块,然后使用块的计算结果进行比较。若没有块时,使用<=>操作符进行比较。sort将生成一个经过排序的新数组并返回它。sort!的对self的排序过程具有破环性。

    to_a/to_ary
    原封不动地返回self。

    to_s
    与self.join($,)相同。

    transpose
    将self看作是由行和列构成的矩阵,然后进行行列互调(将行和列互换)。生成一个新数组并返回它。若原数组为空,则生成空数组并返回它。

    uniq/uniq!
    uniq会删除数组中的重复元素后生成新数组并返回它。剩下的元素会向前移动。uniq!具有破环性,若进行了删除则返回self,若没有删除则返回nil。

    unshift(obj1[, obj2 ...])
    unshift([obj1[, obj2 ...]])
    依次将obj1, obj2 ...插到数组的头部。返回self。

    values_at(index_1, ... , index_n)
    以数组形式返回其索引值与各参数值相等的元素。若指定了超出范围的索引值时,将指派nil与其对应
  • Ruby语言入门(11)- 内部类 - Object

    2013-02-01 15:25:15

    Object类是所有类的超类,它定义了对象的一般行为。

    包含的模块为Kernel。

    定义的方法有:

    = =
    两个对象对象是否相等

    ~ = =
    两个对象是否不等

    = = =
    对象是否为子类

    class
    对象的父类

    clone
    克隆对象

    dup
    克隆对象的内容

    display(out = $stdout)
    将对象输出到 out

    eql?/equal?
    等同于 ==

    extend(module ... )
    将参数所指模块的实例方法追加为self的特殊方法.返回self.

    freeze
    禁止修改对象的内容.返回self.

    frozen?
    若某对象禁止修改其内容则返回真

    hash
    返回对象的哈希表值.


    _ _id_ _ / object_id
    返回与各个对象对应的唯一的整数.

    inspect
    将某对象转为人工可读的字符串并返回该字符串.

    instance_eval(expr, [fname, [lineno=1]])
    instance_eval {|obj| ... }
    在对象的context中计算字符串expr并返回结果.在对象的context进行计算是指,将self设为那个对象然后开始执行.同时,若在字符串/块中定义了方法的话,则相当于定义了self的特殊方法.

    若给出了fname和lineno的话,将假定字符串位于在文件fname的第lineno行,然后开始编译,并能显示文件名/行号等栈跟踪信息. 若给出了块的话,将在对象的context中计算该块并返回结果.self将被传递给块的参数obj.

    instance_of?(klass)
    若self为klass类的直接的实例时,返回真.

    instance_variable_get(var)
    取得并返回对象的实例变量的值.

    instance_variable_set(var, val)
    将val的值赋值给对象的实例变量并返回该值.

    instance_variables
    以字符串数组的形式返回对象的实例变量名.

    is_a?(mod)
    kind_of?(mod)
    只要self是下列任何一个类的实例就返回真::mod类和它的子类,以及包括mod模块的类和它的子类.

    method(name)
    将self的方法name对象化后得到Method对象并返回该对象


    methods
    public_methods
    private_methods
    protected_methods
    methods([inherited_too]) 
    public_methods([inherited_too]) 
    private_methods([inherited_too]) 
    protected_methods([inherited_too]) 

    以字符串数组的形式返回某方法能理解的 public/private/protected 方法名列表.

    nil?
    若receiver为nil则返回真.

    respond_to?(name[, priv=false])
    若对象中包含名为name的public方法时返回真.

    send(name[, args ... ])
    send(name[, args ... ]) { .... }
    __send__(name[, args ... ])
    __send__(name[, args ... ]) { ... }
    调用对象的name方法,并将args传给该方法的参数,然后返回方法的结果.若是带块调用的话,也会把块原封不动地传给方法

    singleton_methods
    singleton_methods([inherited_too]) 
    以字符串数组的形式返回该对象中定义的特殊类名的列表.

    taint
    设定对象的"污染标记".返回self.

    tainted?
    若对象已经有"污染标记"则返回真.

    untaint
    取消对象的"污染标记".返回self.

    to_a/to_ary
    将对象转换为数组并返回该数组.

    to_hash
    将对象隐式地转换为哈希表

    to_int
    将对象隐式地转换为整数

    to_s/to_str
    将对象转换为字符串并返回该字符串.
  • Ruby语言入门(10)- 内部常数

    2013-02-01 15:13:15

    STDIN
    标准输入。$stdin的默认值。

    STDOUT
    标准输出。$stdout的默认值。

    STDERR
    标准错误输出。$stderr的默认值。

    ENV
    表示环境变量的(伪)哈希表。若改变该哈希表的值时,将作为子进程环境而被继承下来。

    ARGF
    由参数(若没的话就使用标准输入)构成的虚拟文件。也就是说,gets与ARGF.gets的意义相同。
    可以使用ARGF.file得到当前读入的文件对象,使用ARGF.filename得到当前读入的文件名。

    ARGV
    传给Ruby脚本的参数。内部变量$*的别名

    DATA
    访问脚本中__END__(脚本终点)以后部分的File对象。

    TOPLEVEL_BINDING
    顶层Binding对象。

    RUBY_VERSION
    Ruby版本

    RUBY_RELEASE_DATE
    Ruby发布日期

    RUBY_PLATFORM
    Ruby平台信息

  • Ruby语言入门(9)- 内部变量

    2013-02-01 14:35:25

    全局变量
    所有以`$'开头的变量

    内部变量
    全局变量中的内部变量(本网页介绍的变量)

    特殊变量
    内部变量中,形如"`$' + 1位数字或符号"的变量

    选项变量
    内部变量中,由命令行选项设定的变量,形如"`$-' +1个选项字符"


    根据变量值的作用域的不同,大致将内部变量划分如下:
    • 局部域, 可看做是线程内的局部变量.
    • 线程局部域,在一个线程内部时是全局域变量,但在不同的线程之间是彼此独立的.
    • 全局域
    属于局部域的:
    $_ 

    gets或readline最后读入的字符串.若遇到EOF则为nil.

    $& (等同于Regexp.last_match[0])

    在当前作用域中,正则表达式最后一次匹配成功的字符串.若最后一次匹配失败,则为nil.

    $~ (等同于Regexp.last_match)

    在当前作用域中,最后一次匹配成功的相关信息(MatchData对象).若对其进行设定的话, 则$&以及$1 ... $9等的值也会发生变化.可以使用$~[n]的形式从该数据中抽取第n个匹配结果($n)

    $‘ (等同于Regexp.last_match.pre_match)

    在当前作用域中,正则表达式最后一次匹配成功的字符串前面的字符串.若最后的匹配失败则为nil。

    $· (等同于Regexp.last_match.post_match)

    在当前作用域中,正则表达式最后一次匹配成功的字符串后面的字符串.若最后的匹配失败则为nil。

    $+

    在当前作用域中,正则表达式最后一次匹配成功的字符串部分中,与最后一个括号相对应的那部分字符串.若最后的匹配失败则为nil.

    $1($2,$3,...)  (等同于Regexp.last_match[1], Regexp.last_match[2],...)

    分别存储着最后一次模型匹配成功时与第n个括号相匹配的值.若没有相应的括号时,其值为nil.

    属于线程局部域的:

    $?

    本线程中最后结束的子进程的状态值。

    $!

    最近发生的异常的信息

    $@

    以数组形式保存着发生异常时的back trace信息. 数组元素是字符串,它显示了方法调用的位置,其形式为:"filename:line"

    $SAFE

    当前线程的安全等级。

    属于全局域的:

    $/

    输入记录分隔符。默认值为"\n"。若将该变量设为 nil 时,将一次读入整个文件。若设为空字符串 "" 则将是段落模式,此时会把2个以上的连续的换行符当作记录切分符。

    $\

    输出记录分隔符。print会在最后输出该字符串。默认值为nil,此时不会输出任何字符。

    $,

    默认的切分字符。若Array#join中省略了参数时或在print的各个参数间将会输出它,默认值为 nil ,等同于空字符串。

    $;

    当String#split中省略参数时的切分字符。默认值为nil,此时将进行特殊的分割。

    $.

    最后读入的输入文件的行号。

    $<

    由参数(若没的话就使用标准输入)构成的虚拟文件。也就是常数ARGF的别名。

    $>

    内部函数print、puts或p等的默认输出对象。初始值为STDOUT。若指定了-i[extension]选项的话,则将使用与读取源同名的文件。

    $0/$PROGRAM_NAME 

    当前运行中的Ruby脚本名.

    $*

    传递给Ruby脚本的参数.内部常数ARGV的别名.

    $$

    当前运行中的Ruby进程的pid

    $:/$LOAD_PATH

    包含一个数组,其内容是load或require加载文件时用的搜索目录列表.

    $"/$LOADED_FEATURES 

    包含以require加载的文件名的数组.这可以防止require多次加载同一个文件.

    $DEBUG

    若此值为真则变成调试模式。它由-d选项进行设定。

    $FILENAME

    虚拟文件ARGF中,当前正在读入的(gets方法正在读的)文件名

    $stdin/$stdout/$stderr 

    标准输入,标准输出,标准错误输出

    $VERBOSE

    警告等级分为三级,分别如下。
    • nil: 不输出警告
    • false: 只输出重要警告(默认)
    • true: 输出所有警告

    $KCODE

    Ruby可识别的多字节字符串的编码。变量值为"EUC" "SJIS" "UTF8" "NONE"之一。可以使用Ke,Ks,Ku,Kn。 "e" "E" 代表 "EUC","s" "S" 代表 "SJIS","u" "U" 代表 "UTF8",而"n" "N" 则代表 "NONE"。默认值为"NONE"。 


    选项变量

    用来显示Ruby解释器命令行信息的变量。其形式为$-?,?的部分是1位选项字符。

    $-0
    $/ 的别名。

    $-a
    若指定了-a时,其值为真。只读变量。

    $-d
    $DEBUG 的别名。

    $-F
    $; 的别名。

    $-i
    若指定了-i[extension]时,它将保存扩展名字符串。否则其值为nil。也可以在脚本中对其进行赋值,此时将在开始读入ARGV中的下一个文件之前进行in-place替换。

    $-I
    $LOAD_PATH 的别名。

    $-K
    $KCODE 的别名。

    $-l
    若指定了-l时,其值为真。只读变量。

    $-p
    若指定了-p时,其值为真。只读变量。

    $-v 
    若指定了-p时,其值为假。只读变量。

    $-w
    $VERBOSE 的别名。

    $-W

    返回由-W[level]指定的值。也就是说,根据$VERBOSE的取值不同
    • nil: 不输出警告 -> 0
    • false: 只输出重要警告(默认) -> 1
    • true: 输出所有警告 -> 2
  • Ruby语言入门(8)- Kernel模块的内部函数

    2013-01-29 16:36:05

    下面是一些常用的kenerl方法

    str

    把字符串str当做外部命令来运行,并以字符串方式返回命令的输出。

    Array(arg)

    调用 arg.to_ary 或 arg.to_a 将参数转为数组并返回结果

    a=Array("test")
    a.class
    => Array

    Float(arg)

    将参数变为浮点数(Float)并返回结果.
    puts Float("10")    
    => 10.0

    Integer(arg)

    将参数变为整数(Fixnum,Bignum)并返回结果.对数值,字符串以外的对象使用to_i方法。

    puts Integer("0d10") 
    => 10

    String(arg)

    调用arg.to_s将参数变为字符串并返回结果。

    a=String("test")
    a.class
    => String

    abort/abort(message)

    以非正常方式结束Ruby程序的运行。

    at_exit { .... }

    在解释器结束工作之前执行指定的块。除去at_exit是个方法这点差异之外,它与END块所进行工作基本相同。


    autoload(const_name, feature)/autoload?(const_name) 

    可以autoload任何类/模块的常数。

    binding

    生成并返回Binding对象。该对象包含变量、方法等的环境信息,它通常用作Eval的第二参数。

    catch(tag) {|tag| .... }

    运行块并返回它的值。若在块的运行过程中,遇到与tag同名的throw的话,将把throw的第二参数的值作为返回值。

    ret = catch(:exit) {
       throw :exit, 25
       some_process()
    }
    puts ret   

    #=> 25

    chop/chop!

    将内部变量$_末尾的字符去掉(若末尾是"\r\n"则去掉2个字符)。chop不改变内部变量$_的内容,chop!改变内部变量$_的内容。

    chomp([rs])/chomp!([rs])

    去掉位于内部变量$_末尾且由rs指定的字符。

    eval(expr[, binding[, fname[, lineno=1]]])

    把字符串expr当作Ruby程序来运行并返回其结果。若给第二参数传递Proc对象或Binding对象的话,将在生成该对象的环境中对字符串进行计算。

    def foo
      a = 1
      binding
    end

    eval("p a", foo)  
    # => 1

    exec(command)/exec(program[, arg1[, arg2[, ...]]])

    执行由command指定的命令.该命令将变成进程执行的代码,所以一旦启动成功,就不会再从该函数中返回.若启动失败,控制权重新回归ruby解释器,然后会引发Errno::EXXX异常.

    exit([status])

    终止Ruby程序的运行.若向status传递了一个整数的话,该整数就将成为Ruby命令的结束状态值.默认的结束状态值是0.

    exit!([status])

    以整数status为结束状态值来终止Ruby程序的运行.默认的结束状态值为-1. exit!与exit不同,它不会进行异常处理.在fork之后,若想终止子进程时可以使用该语句.

    fork/fork { ... }

    使用fork(2)系统调用来制作进程的拷贝.若在父进程中将返回子进程的进程ID,若在子进程中则返回nil.若指定一个块之后再进行调用,则会在生成的子进程中对该块进行计算.

    gets([rs])/readline([rs])

    Ruby解释器在运行时,会把从参数那里得到的文件(若没有的话,就利用标准输入)假设成一个虚拟文件(可以使用内部变量$<或ARGF访问该虚拟文件),然后从该虚拟文件中读入一行,并返回字符串.若到达文件尾部时返回nil.

    使用rs指定的字符串作为行的切分符号.rs的默认值取自内部变量$/.读入的字符串也被存入内部变量$_中.

    若将rs设为nil的话,则意味着读入文件的全部内容而忽略行的切分.若设为空字符串""的话,会把连续的换行当做行的切分符(段落模式).

    readline的功能与gets相同,但是当它遇到文件结尾时会引发EOFError异常.

    global_variables

    返回程序中已定义的全局变量(以'$'开头的变量)名的数组.

    gsub(pattern[, replace])
    gsub!(pattern[, replace])
    gsub(pattern) {|matched| ... }
    gsub!(pattern) {|matched| ... }

    在内部变量$_所包含的字符串中,将符合pattern的部分替换为replace,然后返回结果.若省略参数replace时,该方法将演变为迭代器,以块的计算值进行替换操作.将匹配的字符串以参数的形式传递给块.

    $_ = "foobar"

    puts gsub(/o+/) {|m|
      m.upcase
    }

    # => "fOObar"

    block_given?

    若某方法带块则返回真,否则返回伪。

    load(file[, priv])

    加载Ruby程序file并予以执行.若file是绝对路径,则从file开始加载.若file是相对路径,则依次搜索内部变量$:所指定的路径,并加载第一个搜索到的文件.此时,若$:中的元素是以"~"(tilde)开头的话,就把它扩展为环境变量HOME的值.

    若加载成功则返回true,若失败则引发LoadError异常.

    [require与load之间的区别]

    require对于相同的文件只会加载一次,而load则是无条件的加载.另外,require会自动补全扩展名,如.rb或.so等.而load则没有该功能.一般的典型用法是,使用require加载库,而使用load加载配置文件等.

    local_variables

    返回当前作用域中已定义的局部变量名的数组.

    loop { ... }

    (只要不被中断就)反复对块进行计算.

    open(file[, mode[, perm]])/open(file[, mode[, perm]]) {|io| ... }

    打开file并返回File对象.mode可以是下列,省略时默认为"r".
    • "r", RDONLY: 以读取模式打开文件.
    • "w", WRONLY|CREAT|TRUNC: 以写入模式打开文件.打开文件时,若文件已存在就清空文件内容.
    • "a", WRONLY|CREAT|APPEND: 以写入模式打开文件.通常把写入内容添加到文件结尾.
    若有"+"的话,就以读写两用模式(RDWR)打开文件:
    • "r+": 将文件的读写位置设在开头.
    • "w+": 与"r+"一样.打开文件时,若文件已存在就清空其内容.
    • "a+": 与"r+"一样.打开文件时,若文件已存在,就把读写位置设在文件结尾.
    可在上述任意一项后面添加"b"(如"r+b")标志.此时,将以二进制方式打开文件(只限于以文本/二进制方式来区分文件的系统).

    第三参数perm与open(2)的第三参数是一样的,它以整数的形式说明了文件在CREAT时的访问权限。若第二参数不是数值形式的话,该参数将被忽略。它的默认值是0666。

    若文件名以`|'开头时,其后的字符串会被当作命令来执行。另外,将生成管线(pipeline)来应对命令的标准输入输出。

    若文件名为"|-"的话,open将生成Ruby的子进程,并返回与子进程之间的管道(pipe)(IO对象)。(此时的运作与IO.popen相同。File.open没有生成管线的功能)。

    当open与块同时被调用时,open将打开文件并执行块,当块的运行终止后就关闭文件。此时返回块的计算结果。请看下例。

    open(path, mode) do |f|
       ...
    end

    # 等效代码
    f = open(path, mode)
    begin
       ...
    ensure
      f.close
    end


    p(obj, [obj2, ...])

    等同于print。

    print([arg1[, arg2, ...]])

    依次输出参数。若没有得到参数则输出变量$_的值。若把非字符串对象传给参数的话,将对该对象使用to_s方法将其变为字符串后输出。若是nil的话则输出字符串"nil"。

    printf([port, ]format[, arg[, ...]])

    类似于C语言的printf,它将按照format将参数格式化为字符串,然后输出到$>。当第一参数是IO的子类的实例时,将对该对象进行输出。若没有任何参数时,将不作反应。

    proc { ... }
    lambda { ... }
    proc
    lambda

    在给出的块中生成过程对象(Proc的实例)并返回它(等同于Proc.new)。

    若没有给出块的话,将返回主调(caller)方法所指的块。若主调方法没有块时,将引发ArgumentError异常。

    putc(ch)

    将字符ch输出到$>。若ch是数字的话,将输出对应于0~255的字符。若ch是字符串的话,将输出字符串中的第一个字符。

    puts([obj[, obj2[, ....]]] )

    依次将obj和换行符输出到$>。若没有参数的话则只会输出换行符。

    若参数是数组,则依次输出数组元素和换行符。若将既非数组又非字符串的对象传递给参数时,将尝试使用to_ary方法将其化为数组,再使用to_s方法将其化为字符串。若是nil则输出字符串"nil"。


    raise
    raise(exception)
    raise(message)
    raise(error_type, message [, backtrace])
    fail(error_type, message [, backtrace])

    引发异常,若没有参数时,将再次引发本线程本块内最后被rescue的异常对象($!)。若没有这样的异常时,将引发RuntimeError异常。

    begin
      open("nonexist")
    rescue
      raise   # => `open': No such file or directory - "nonexist" (Errno::ENOENT)
    end


    只有一个参数,且该参数为字符串时,将以该字符串为message来引发RuntimeError异常。若该参数为异常类或异常对象时,将引发该异常。

    raise "error message"    # => -:1: error message (RuntimeError)
    raise ArgumentError      # => -:1: ArgumentError (ArgumentError)
    raise ArgumentError.new  # => -:1: ArgumentError (ArgumentError)

    有2或3个参数时,将以第二参数为message来引发第一参数所指的异常。此时是以异常类或异常对象来指定异常的。而第三参数则是发生异常时的栈跟踪(track trace),它的形式必须与caller的返回值一致。

    raise ArgumentError, "error message"
    # => -:1: error message (ArgumentError)
    raise ArgumentError, "error message", ["file1:99","file2:999:in `method'"]
    # => file1:99: error message (ArgumentError)
                  from file2:999:in `method'

    若将非异常的类或对象赋予第一参数时,实际上发生的异常正是该对象的exception方法的返回值。

    class MyException
      def exception
        ArgumentError.new
      end
    end

    raise MyException.new
    # => -:7: ArgumentError (ArgumentError)

    采用第二种形式来指定参数时,该参数将被赋予exception方法。

    class MyException
      def exception(mesg)
        ArgumentError.new(mesg)
      end
    end

    raise MyException.new, "error message"
    # => -:7: error message (ArgumentError)


    rand([max=0])

    产生一个0至max(不含)之间的随机数。

    require(feature)
    从加载路径$:开始搜索Ruby库feature,若该库尚未被加载就立即加载。

    scan(re)/scan(re) {|matched| ... }

    与$_.scan一样。

    select(reads[, writes[, excepts[, timeout]]])

    与IO.select一样。

    set_trace_func(trace_proc)

    在Ruby解释器执行程序的过程中,每当发生方法调用或对表达式进行计算等事件时都将执行trace_proc过程对象

    set_trace_func lambda {|event, file, line, id, binding, klass|
        # ....
    }

    event表示发生事件的类别。详细内容如下:

    • "line" ... 表达式的计算。
    • "call" ... 方法调用。
    • "return" ... 从方法调用中返回。
    • "c-call" ... C(语言)方法的调用。
    • "c-return" ... 从C(语言)方法调用中返回。
    • "class" ... 进入类定义、特殊类定义或模块定义中。
    • "end" ... 类定义、特殊类定义或模块定义的结束。
    • "raise" ... 发生异常。
    file运行中的程序的源文件名(字符串)。

    line运行中的程序的源文件行号(整数)。

    id根据event的不同,将使用下列之一。与第六个块参数klass相对应。
    • line Symbol对象,它表示最后被调用的方法。在顶层中则为nil。
    • call/return/c-call/c-return Symbol对象,它表示被调用/return的方法。
    • class/end nil。
    • raise Symbol对象,它表示最后被调用的方法。在顶层中则为nil。

    binding Binding对象,它表示运行中的程序的状况(context)。

    klass根据event的不同,将使用下列之一。与第四个块参数id相对应。
    • line Class对象,它表示最后被调用的方法的所属类。在顶层中则为false。
    • call/return/c-call/c-return Class对象,它表示被调用/return的方法的所属类。
    • class/end false。
    • raise Class对象,它表示最后被调用的方法的所属类。在顶层中则为false。
    sleep([sec])

    使程序暂停sec秒。也可以将sec设为浮点数。省略sec时,若没有显式地(SIGALRM或其他线程发出的Thread#run)终止睡眠的话,将一直sleep下去。返回值是实际睡眠的秒数(整数)

    spawn(cmd, [arg, ...]) 

    基本上等同于system,但它不会等待子进程的结束。返回生成的子进程的进程ID。

    split([sep[, limit]])

    使用sep模型将$_中的字符串分割成limit个部分后转化为数组,然后返回该数组。

    sprintf(format ... )/format(format ... )

    sprintf对format字符串进行解释,格式化参数后返回结果。使用format时,等同于sprintf。

    srand([seed])

    设定rand的随机数的种子,返回旧的初始值(第一次返回0)。若省略初始值时,则以当前时刻、进程ID或srand的调用次数为基础生成一个种子。

    sub(pattern[, replace])
    sub!(pattern[, replace])
    sub(pattern) {|matched| ... }
    sub!(pattern) {|matched| ... }

    在内部变量$_所指的字符串中,将首个匹配pattern的部分替换为replace,然后返回结果.若省略参数replace时,该方法将变为迭代器,以块的计算值进行替换操作.将匹配的字符串以参数的形式传递给块

    syscall(num, arg ... )

    执行num号码所对应的系统调用。将第二参数以后的部分传给系统调用作为其参数。参数必须是字符串或整数。

    system(command)
    system(program[, arg1[, arg2[, ...]]])

    执行command,成功(子进程以 status 0 的状态结束时)则返回真,失败(包括不能执行命令)则返回伪。可参照变量$?来获取结束状态值(status)。

    test(cmd, file1 [, file2])

    进行文件测试。

    trace_var(varname, hook)
    trace_var(varname) {|newval| .... }

    注册钩子以监视对全局变量varname所进行的赋值。varname可以是字符串或Symbol。这里所说的“全局变量”是指以“$”开头的变量,包括特殊变量。

    untrace_var(varname[, hook])

    取消与全局变量varname有关的钩子。若指定了hook的话,将只会取消该钩子。若省略hook或将其设为nil时,将取消varname所有的钩子。返回取消钩子的数组。

    warn(mesg)

    依次输出mesg和换行符到$stderr之中。若内部变量$VERBOSE为nil时,则不会输出。
  • Ruby语言入门(7)- 控制语句

    2013-01-29 16:17:49


    条件分支

    if 表达式 [then]
      表达式 ...
    [elsif 表达式 [then]
      表达式 ... ]
    ...
    [else
      表达式 ... ]
    end

    if age >= 12 then
      print "adult fee\n"
    elseif age <6 then
     print "no fee\n"
    else
      print "child fee\n"
    end


    if 修饰句

    print "adult fee\n" if age >= 12

    unless 表达式 [then]
      表达式 ...
    [else
      表达式 ... ]
    end

    unless baby?
      feed_meat
    else
      feed_milk
    end

    unless 修饰句

    print "stop\n" unless valid(passwd)

    case [表达式]
    [when 表达式 [, 表达式] ...[, `*' 表达式] [then]
      表达式..]..
    [when `*' 表达式 [then]
      表达式..]..
    [else
      表达式..]
    end

    case $age
    when 0 .. 2
      "baby"
    when 3 .. 6
      "little child"
    when 7 .. 12
      "child"
    when 13 .. 18
      "youth"
    else
      "adult"
    end


    循环

    while 表达式 [do]
       ...
    end

    ary = [0,2,4,8,16,32,64,128,256,512,1024]
    i = 0
    while i < ary.length
      print ary[i]
      i += 1
    end


    表达式 while 表达式


    sleep(60) while io_not_ready?

    until 表达式 [do]
       ...
    end

    until f.eof?
      print f.gets
    end


    表达式 until 表达式

    print(f.gets) until f.eof?

    for  表达式  in 表达式 [do]
      表达式..
    end

    for i in [1, 2, 3]
      print i*2, "\n"
    end


    过程

    break将退出最内层的循环。所谓循环是指,下列之一

    while
    until
    for
    迭代

    next将跳转到最内侧循环的头部

    redo不检查循环条件,重新开始当前循环。

    retry,意味着重启迭代器

    return结束方法的运行,且把表达式的值设定为方法的返回值。若给出了2个以上的表达式,则将把这些表达式化为一个数组,然后把该数组设定为方法的返回值。若省略表达式,将返回值设为nil。



  • Ruby语言入门(6)- 字面值

    2013-01-29 15:48:28

    字面值

    我们把类似字符串“hello world”这样可以直接写入Ruby程序中的值叫做字面值。

    数值字面值

    123 整数
    -12 带符号的整数
    1.2 浮点数
    ?a a的AscII码

    字符串字面值

    "this is a string expression\n" 字符串
    'a' 字符
    'aaa' 字符串  

    在被单引号括起来的字符串中,除了\\(反斜线本身)、\'(单引号)和行尾的\(忽略换行)以外,不会对字符串内容作任何处理。

    字符串中,以\来处理的字符有:
    \t Tab
    \n 换行
    \r 回车
    \f 换页
    \b 退格
    \e Esc
    \s 空白
    \\ \
    \' '

    字符串中,以%来处理

    %!STRING! : 双引号中的字符串
    %Q!STRING! : 同上
    %q!STRING! : 单引号中的字符串
    %x!STRING! : 命令输出
    %r!STRING! : 正则表达式
    %w!STRING! : 字符串数组(以空白字符切分各元素)
    %W!STRING! : 字符串数组(以空白字符切分各元素)。展开式、反斜线表示法都有效
    %s!STRING! : 符号。展开式、反斜线表示法都无效

    实例:
    %(()) => "()"
    %w(foo bar baz) => ['foo', 'bar', 'baz']
    %w(foo\ bar baz)=> ["foo bar", "baz"]


    字符串中,以展开式来处理

    ruby = "RUBY"
    "my name is #{$ruby}" #=> "my name is RUBY"
    'my name is #{$ruby}' #=> "my name is #{$ruby}"
    "my name is #$ruby" #=> "my name is RUBY"

    在以双引号(")括起来的字符串表达式、命令字符串以及正则表达式中,可以使用“#{表达式}”把表达式的内容(以字符串的形式)嵌入其中。若表达式是以($,@)开始的变量的话,则可以省略{}部分,只使用“#变量名”的形式即可.


    集成字符串字面值

    <<[-]["'`]标识符["'`]
       ...
    标识符

    print <<EOS      # (从这里开始)直到标识符 EOS 之前的部分就是字面值
      the string
      next line
    EOS

    等同于:
    print "  the string\n  next line\n"


    可以当作一个整体进行应用:
    # 将集成字符串用作被调
    p  <<LABEL.upcase
    the lower case string
    LABEL

    # => "THE LOWER CASE STRING"

    正则表达式

    被/括起来的部分就是正则表达式,例如:/Ruby/i

    数组表达式

    被[]括起来的部分就是数组表达式,例如:[1, 2, 3]

    哈希表表达式

    被{}括起来的部分就是哈希表达式,例如:{1=>2, 2=>4, 3=>6}

    范围对象

    范围表达式两端都是数值字面值时,每次计算都将返回同一个对象。除此以外,每次计算时都会返回新的范围对象。例如: [1..9]

    符号

    符号应用的语法如下:

    :标识符
    :变量名
    :操作符

    指定给Symbol字面值的操作符,必须是那些可以作为方法进行再定义的操作符


  • Ruby语言入门(5)- 变量

    2013-01-29 14:51:42

    局部变量

    标识符首位是小写字母或“_”,则该变量就是局部变量。

    局部变量的作用域起始于声明处,结束于该声明所在的块、方法定义、类/模块定义的结尾。

    但也有例外。若块已经变成过程对象的话,则局部变量将一直持续到该过程对象终结为止。若多个过程对象引用同一个作用域的话,局部变量将被这些对象所共享。

    实例变量

    以@开始的变量是实例变量,它属于特定的对象。可以在类或子类的方法中引用实例变量。若引用尚未被初始化的实例变量的话,其值为nil。

    类变量

    以@@开始的变量是类变量。在类的定义中定义类变量,可以在类的特殊方法、实例方法等处对类变量进行引用/赋值。类变量可以被当作被类、子类以及它们的实例所共享的限制性全局变量。

    全局变量

    以$开始的变量是全局变量,可以在程序的任何地方加以引用(因此需要特别留意)。全局变量无需变量声明。引用尚未初始化的全局变量时,其值为 nil。

    伪变量

    除普通的变量之外,还有一种叫做伪变量的特殊变量。

    self 当前方法的执行主体
    nil NilClass类的唯一实例
    true TrueClass类的唯一实例
    false FalseClass类的唯一实例。nil 和 false 表示“伪”。

    __FILE__ 当前源文件名
    __LINE__ 当前源文件中的行号

    伪变量的值不可改变,若对伪变量赋值将引发语法错误。

    常数

    以大写字母([A-Z])开始的标识符是常数.常数的定义(和初始化)由赋值过程完成.不能在方法中对常数进行定义.若对已定义的常数进行赋值的话,会出现警告信息.若引用未定义的常数的话,则会引发NameError异常.


    类变量与常数的区别

    类变量可以重复赋值,常数不能。
    类变量不能在类的外部直接引用,只能在其继承类中引用/赋值。
    常熟可以在类的外部直接引用。

    类变量与实例变量的区别

    类变量可在子类中引用/赋值,而实例变量只能被引用。
    类变量可在类实例的方法中引用/赋值,而实例变量只能被引用。
  • Ruby语言入门(4)-表达式

    2013-01-29 14:41:37

    在ruby中,将表达式连接起来就构成程序。

    使用分号(;)换行将表达式分隔开来。但反斜线后出现的换行并非分隔符,它表示该行将继续下去。

    例:
    puts "hello \
    world!\n"

    Ruby的表达式包括:变量常数、各种字面值、相关计算赋值、if或while等控制结构方法调用类/方法的定义。还可以使用括号将表达式括起来进行群组化。



    Ruby的表达式包括返回值的表达式和不返回值的表达式。
    空表达式 () 返回nil。
    不返回值的表达式: while, until, while 修饰表达式, until 修饰表达式
    不能用作参数的表达式: and, or, not, if/unless/rescue 修饰表达式

    Ruby解释器在读取程序时,若遇到下列标识就会停止
    文件的末尾(eval中字符串的末尾)
    ^D(control D)、^Z(control Z)
    只包含__END__的行(若前后出现空白字符将无法辨认)
  • Ruby语言入门(3)- 标识

    2013-01-29 14:31:38

    标识符

    Ruby的标识符的首位由字母或下划线('_')构成,后面部分可以是字母、下划线('_')或数字。对标识符的长度没有限制。

    foobar
    _ruby_is_simple

    注释行

    Ruby以#开始的行当作注释行来处理。 字符串内部和数值字面值中的“#”除外。

    # this is a comment line

    内嵌文档

    行首为=begin的行开始到行首为=end的行为止的部分就是内嵌文档,这部分代码被忽略,一般用于较长的解释

    =begin
    the everything between a line beginning with `=begin' and
    that with `=end' will be skipped by the interpreter.
    =end

    保留字

    下列词语就是Ruby的保留字:

    BEGIN    class    ensure   nil      self     when
    END      def      false    not      super    while
    alias    defined? for      or       then     yield
    and      do       if       redo     true
    begin    else     in       rescue   undef
    break    elsif    module   retry    unless
    case     end      next     return   until

    保留字不可用作类名和变量名。

  • Ruby语言入门(2)- 对象

    2013-01-29 14:18:19

    Ruby是一种强对象语言。

    Ruby所能处理的都是对象。

    Ruby操作对象时的办法只有一种,那就是方法调用。

    对象所属的类决定了对象所包含的方法,对象是类的“实例”。

    类决定了其对象的方法,对象调用方法的方式是:类+方法名。

    类能继承父类的方法,这是一种继承关系。

    而引入的模块,是一个包含了完整的方法的非类。

    调用方法时可以传递其他对象,这些其他对象就是“参数”。可接受的参数是在定义方法时确定的,不可改变。

    类本身也可以看作是一个对象。例如:查询某方法是否存在,定义方法或者取消方法。


    类的定义方式

    class ClassName [< 超类表达式]
      表达式
    end

    模块的定义方式

    module ModuleName
      模块内容
    end

    方法的定义方式

    def method_name(arg, argwithdefault=expr, *restarg, &block)
      方法内容
    end

    BEGIN/END

    当代码中有BEGIN/END圈起的代码块,会被先执行。



  • Ruby语言入门(1)- 命令行

    2013-01-29 14:05:30

    ruby的命令行如下:

    ruby [ option ...] [ -- ] [ programfile ] [ argument ...]

    "option"指命令行选项。
    "--"则显式地表明选项字符串到此结束。
    "programfile"是装载Ruby脚本的文件。若省略不写或者写成"-"时,Ruby会把标准输入当做Ruby脚本进行处理。
    argument中的字符串将变成内部常数ARGV的初始值。

    常用的option有:

    -Cdirectory
    执行脚本之前,先移动到指定目录。

    -c
    只对脚本进行编译,而并不执行。编译后若没发现语法错误,则显示“Syntax OK”。

    -d/--debug
    以调试模式执行脚本/将$DEBUG设置成true。

    -e script
    额外执行一行代码,可以有多个-e出现

    例如:ruby -e "5.times do |i|; puts i; end"

    -h/--help
    显示命令行选项的简介

    -Idirectory
    指定(追加)加载文件的路径。指定的目录将被追加到Ruby的数组变量($:)中,即$LOAD_PATH。

    -w/-W[level=1]
    打开warning信息/设置warning的级别

    --version
    版本信息

    programfile指定的脚本是以'#!'开头的文件。

    若第一行中包含'ruby'的话,则'ruby'左侧的部分将被忽略,右侧以'-'开头的部分被视为选项。
    若第一行中不包含'ruby'时,将替代OS把'#!'后面的字符串看成命令行,然后启动解释器。

    例如,用Ruby运行下面的shell脚本时将启动sh。

    #!/bin/sh -vx
    echo "$@"

  • Watir Webdriver的editor处理

    2013-01-28 15:00:47

    很多网站使用了WYSIWYG Editor来输入文本,比如51testing这样的。Watir内置了一些方法可以对其进行处理:

    一种是先查找到editor所在的iframe,然后使用send_keys的方法来发送字符串,需要注意的是,包含该iframe的窗口必须是在所有的窗口最上方.

    另外一种方式是书写一段javascript语句,通过对browser进行内容输入,这种方法最常见

    例如CKEditor

    require 'watir-webdriver'
    b = Watir::Browser.new :firefox
    b.goto 'http://ckeditor.com/demo'
    b.execute_script("CKEDITOR.instances['editor1'].setData('hello world');")
    b.frame(:title => 'Rich text editor, editor1, press ALT 0 for help.').send_keys 'hello world again'

    这个例子就是向iframe直接通过send_keys发送字符

    而使用TinyMCE Editor的例子,就是执行一段javascript语句

    require 'watir-webdriver'
    b = Watir::Browser.new
    b.goto 'http://tinymce.moxiecode.com/tryit/full.php'
    b.execute_script("tinyMCE.get('content').execCommand('mceSetContent',false, 'hello world' );")
    b.frame(:id => "content_ifr").send_keys 'hello world again'

  • Watir Webdriver支持的特殊键

    2013-01-28 14:02:03

    Watir Webdriver可以向element发送特殊的key值,可以有如下几种方式:

    向browser发送Enter键,等于在当前页面敲击回车,作用于当前焦点处:
    browser.send_keys :enter

    向指定的element发送多个键值:
    browser.element.send_keys [:control'a'], :backspace

    也可以overide一些元素的click事件:
    browser.element.click(:shift:control)

    可以指定的key值有:
    :null
    :cancel cancel键
    :help help键
    :backspace 退格键
    :tab 制表符键
    :clear 清除键
    :return 回车符键
    :enter 回车键
    :shift 右shift键
    :left_shift 左shift键
    :control 右ctrl键
    :left_control 左ctrl键
    :alt 右Alt键
    :left_alt 左Alt键
    :pause 暂停键
    :escape Esc键
    :space 空格键
    :page_up PgUp键
    :page_down PgDn键
    :end End键
    :home Home键
    :left 左移
    :arrow_left 左移键
    :up 上移
    :arrow_up 上移键
    :right 右移
    :arrow_right 右移键
    :down 下移
    :arrow_down 下移键
    :insert 插入键
    :delete 删除键
    :semicolon 分号键
    :equals 等号键
    :numpad0 数字0键
    :numpad1 数字1键
    :numpad2 数字2键
    :numpad3 数字3键
    :numpad4 数字4键
    :numpad5 数字5键
    :numpad6 数字6键
    :numpad7 数字7键
    :numpad8 数字8键
    :numpad9 数字9键
    :multiply *号键
    :add +号键
    :separator |键
    :subtract -键
    :decimal .键
    :divide /键
    :f1 F1键
    :f2 F2键
    :f3 F3键
    :f4 F4键
    :f5 F5键
    :f6 F6键
    :f7 F7键
    :f8 F8键
    :f9 F9键
    :f10 F10键
    :f11 F11键
    :f12 F12键
    :meta windows键(windows平台)
    :command 等同:meta键,别名
1825/10<12345678910>
Open Toolbar