探索Ruby正则表达式算法(译)

来源:Exploring Ruby’s Regular Expression Algorithm(2012)

ps. 业余翻译的,求轻拍。有什么问题可以直接指出。

大家都熟悉正则表达式,它是开发者的“瑞士军刀”。不管你想查找哪种信息,解析哪些字符串,总有一种正则表达式适合你。事实上,你可能用过很久的ruby所使用的正则表达式了——正则表达式已经被集成到几乎所有主要的语言中好多年了:Perl、javascript、PHP、Java等等。ruby支持是在90年代中期,而正则表达式是在60年代中期发明的,早了30年。

但是正则表达式是怎样工作的呢?如果你对正则表达式引擎后面的计算机原理感兴趣的话,可以读一下这三篇Russ Cox写的极棒的文章:

在这里我不打算重复Russ的内容。但是我准备在第二篇文章中快速的解释一下ruby所使用的“无递归的回溯实现”, 这意味着它可能也会像perl正则表达式一下慢吞吞。就是说,这意味着Ruby并没有使用目前最主流的正则表达式实现方法——Thompson NFA,也就是Russ第一篇文章中所描述的。

今天我们细看一下Oniguruma,也就是Ruby所使用的正则表达式引擎。我们使用一些插图来表现一些简单的正则示例,以此来弄清楚在使用正则的时候是Ruby内部是如何工作的——它比你想象的要复杂多了。

继续阅读

几个语言中的迭代器

上次有朋友说python的迭代器很好用,就是不好理解,我说其实php也有迭代器的,只是很多人不知道而已。

python迭代器:

先说说python的迭代器,python的迭代器使用yield关键字来实现,可以被for调用。

还是来拿读文件来说事,我们有一个文件,里面的数据都是TAB分隔,如果我们想实现一个一行行读取的库核心的地方可以使用迭代器来写:

tab文件(html输出后估计tab变成了空格,复制的同学请注意):

迭代器代码:

这里涉及迭代器的部分在于read方法中的yield迭代器,虽然是for循环,在yield调用一次以后会挂起等待下一次调用yield,所以很多人在这里需要理解很久。所以yield在while内自然也是一样的效果。

继续阅读

sinatra “incompatible character encodings: ASCII-8BIT and UTF-8”问题

使用sinatra的时候出现了“incompatible character encodings: ASCII-8BIT and UTF-8”报错。这个应用是使用haml并且在haml里使用markdown方法去读markdown文件来作为模板解决方案的,如果Tilt读取haml是一种编码格式而rdiscount读取markdown是另一种编码,应该会产生这问题,于是google了一下,找到如下一个解答:

Incompatible character encoding in simple Sinatra app

其原因大概是Tilt使用了IO.binread读取后编码为ASCII-8BIT,而RDiscount则读取文件后转换为需要的编码格式,但如果需要的格式是ASCII-8BIT时就会失败,它直接把utf-8编码的字符串传给了Tilt。此类问题出现在ruby1.9+的版本上。可以通过使用File.read代替Tilt默认的IO.binread,或者读取完后强制转换成你需要的编码格式:

示例代码:

示例中使用的是erb模板,haml也是一样的,我使用force_encoding的解决方案,运行通过。

我遇到问题时各个包版本如下:

  • ruby:2.0.0
  • Tilt:1.3.6
  • rdiscount:2.0.7.1

我的某个服务器就没出现这问题,应该是和某些版本有关的。

ruby1.9或2.0 irb不支持中文的解决

今天重新编译了一下ruby,发现irb输入不了中文了,出现类似如下的字符串:

'\U+FFE4\U+FFB8\U+FFAD\U+FFE6'

google了一下发现是readline的问题,似乎只有mac下才有这问题。于是重新编译一次,把readline的地址制定到 --with-opt-dir=/path/to/your/readline。

编译安装后就会发现一切都解决啦。

ruby动态创建类和方法

很多人通过Class.new和define_method方法来动态创建类和方法。

怎么创建到执行时才知道类名的类呢,答案是const_set方法,将这个常量和类连接在一起,放在Object下面就可以了。定义方法自然是define_method,以下是示例代码:

大致情况就这些,大家可以根据自身情况使用。

使用EventMachine

译自:Playing with eventmachine

最近这几周,我在工作中用了好几次 Ruby EventMachine,虽然它的 RDoc 还不错,但要是真想搞明白这玩意儿恐怕还是要花些功夫,所以我就写了这篇文章。

首先要弄明白的是,究竟什么是EventMachine,在什么场景会用到它。简而言之,EM(EventMachine)是个事件循环监听器(Event loop)。一旦你使用了EventMachine,它便随着ruby的主线程启动,然后去做他自己该做的事情。EM可以监听sockets、监听文件描述符、控制定时器等大量的事情。当你监听的事件触发时,EM会触发你的回调方法,如此一来你便可以处理这些事件,处理完之后再把事件控制权交还给EventMachine。

你也可以让EventMachine执行一大堆和你主要逻辑无关的代码,当这一大堆代码执行完的时候再让回调方法在主要逻辑连接上的任何请求上执行。

我们来用一段代码增进对它的理解:

例1.定时器:

我们来瞧一下这段简单的代码吧。在程序执行之前,需要先安装好 Eventmchine,我们可以通过rubygems来安装(gem install eventmachine),然后我们在程序里引入需要的部分(require 'eventmachine')。你可能会奇怪为什么我有的地方用了EventMachine,有的地方用了EM,其实他们是一样的,你可以随意对调。EM写起来比较短,不过我有时候也会用EventMachine。EventMachine#run方法用来开启主事件循环监听,在这段代码块里你可以添加自己希望的各种功能,比如某种服务,或者定时器之类。

继续阅读

ruby调用执行shell命令的方法

ruby执行shell的方法主要有:

1.Exec方法:

Kernel#exec方法通过调用指定的命令取代当前进程:

值得注意的是,exec方法用echo命令来取代了irb进程从而退出了irb。主要的缺点是,你无法从你的ruby脚本里知道这个命令是成功还是失败。

2.System方法。

Kernel#system方法操作命令同上, 但是它是运行一个子shell来避免覆盖当前进程。如果命令执行成功则返回true,否则返回false。

3.反引号(Backticks,Esc键下面那个键)

这种方法是最普遍的用法了。它也是运行在一个子shell中。

继续阅读

编译ruby2.0.0后gem报openssl错误的解决方法

mac osx下编译安装完ruby2.0.0的时候,使用gem install命令会报:Could not load OpenSSL之类的错误,本以为是openssl没装,于是

还有不行⋯⋯终于执行:

然后make clean,重新编译一下,发现gem又可以正常使用了。

ps.貌似也可以在编译的时候添加下面一个选项:

这样就可以load额外的openssl库,而不使用系统的。

比如编译时用:

不过这两个方法前提都是你自己编译安装了openssl,或者使用brew等工具编译安装过它。

Ruby Rake任务简介(转)

RakeMakeAnt

Rake的意思是Ruby Make,一个用ruby开发的代码构建工具。Rake的英文意思是耙子,一种很朴实的劳动工具。真的是很贴切,Rake正是一个功能强大、勤勤恳恳的劳动工具。

但是,为什么Ruby需要Rake

Ruby代码不需要编译,为什么需要Rake?其实,与其说Rake是一个代码构建工具,不如说Rake是一个任务管理工具,通过Rake我们可以得到两个好处:

  1. 以任务的方式创建和运行脚本
    当然,你可以用脚本来创建每一个你希望自动运行的任务。但是,对于大型的应用来说,你几乎总是需要为数据库迁移(比如Rails中db:migrate任务)、清空缓存、或者代码维护等等编写脚本。对于每一项任务,你可能都需要写若干脚本,这会让你的管理变得复杂。那么,把它们用任务的方式整理到一起,会让管理变得轻松很多。
  2. 追踪和管理任务之间的依赖
    Rake还提供了轻松管理任务之间依赖的方式。比如,“migrate”任务和“schema:dump”任务都依赖于 “connect_to_database”任务,那么在“migrate”任务调用之前,“connect_to_database”任务都会被执行。

在哪里可以获得Rake

Rake的主页是在http://rake.rubyforge.org/,在这里你可以获得Rake的简单介绍,API以及一些有用文档的链接。可以在http://rubyforge.org/frs/?group_id=50获得最新版的Rake,在作者写作时,最新版本是0.7.3。

Rake脚本编写 一个简单脚本

Rake的脚本相当简单,下面用一个例子进行说明。假设你是一个勤劳的家庭型程序员,在周末你打算为你的家人做一些贡献。所以你为自己制定了三个任务:买菜、做饭和洗衣服。打开你的文本编辑器,创建一个名叫rakefile的文件(Rake会在当前路径下寻找名叫Rakefile、rakefile、RakeFile.rb和rakefile.rb的rake文件),并输入如下内容:

打开命令行工具,进入这个文件所在目录,然后运行下面的命令,大致应该类似如下结果:

继续阅读

闲话

最近手欠把服务器升级到了ruby2.0.0,个人不是很喜欢passenger这种编译成nginx模块的方式,顺手换成了unicorn,换unicorn而不使用thin的原因是unicorn名字比较好听……然后写unicorn的文件,各种弄,总觉得unicorn部署起来并没有*unix的感觉,于是又换了thin试试,觉得还是这个顺手,只要thin install,修改配置,然后chkconfig就可以了。

又因为自己乱删服务器里面的rails,导致pipeline合并js文件出了问题,自己一顿暴走,最后终于发现是瞎玩给弄的,看来以后要老实点……

目前ruby2.0.0下跑着完全没问题,只等rails4.0 release了。