- 浏览: 1400404 次
- 性别:
- 来自: 火星
文章分类
最新评论
-
aidd:
内核处理time_wait状态详解 -
ahtest:
赞一下~~
一个简单的ruby Metaprogram的例子 -
itiProCareer:
简直胡说八道,误人子弟啊。。。。谁告诉你 Ruby 1.9 ...
ruby中的类变量与类实例变量 -
dear531:
还得补充一句,惊群了之后,数据打印显示,只有一个子线程继续接受 ...
linux已经不存在惊群现象 -
dear531:
我用select试验了,用的ubuntu12.10,内核3.5 ...
linux已经不存在惊群现象
在ruby中内置了正则表达式,如果你的ruby版本是1.9或者更后面的版本的话,你的正则表达式引擎将会是一个叫做Oniguruma的东西。这是一个新的引擎,代替了1.8版本中的这则表达式引擎,我们后面会介绍到它。
1编译正则表达式:
正则表达式能够使用Regexp.compile 方法进行编译(这个方法同Regexp.new方法是同义的),
参数可以是一个字符串或者一个正则式(这边要注意一个问题,如果参数是正则式的话,他所附带的参数将会被传播,你可以不用指定后续的第二个参数,这个马上就会看到),看下面的例子:
第二个参数,如果存在的话可以是由||连接起来的 下面几个值Regexp::EXTENDED, Regexp::IGNORECASE, Regexp::MULTILINE。第二个参数如果是true代表大小写不敏感,否则代表大小写敏感。可是如果参数是一个正则式的话,第二个参数将会被忽略.
第三个参数启用对正则表达式的多字节支持。同样的如果使用正则式,它将会被忽略.
最后,我们还可以直接使用//来定义正则表达式,而不需要任何compile方法。。
2 转义特殊字符
我们可以使用Regexp.escape 方法来转义特殊字符,转义的返回值就是所能匹配的正则表达式,也就是说 Regexp.new(Regexp.escape(str)) =~str一定返回true.
3使用锚
一个锚是一个特殊的匹配一个字符串中的位置的表达式。
最简单的锚就是 ^和$,它们分别匹配一个字符串的开始或者结尾的位置.
可是这边小小的撒了个谎,其实^和$并不是真正的匹配字符串的开始或结尾,它们会分隔多行,也就是说如果有多行的话,他们会匹配多个开始和结尾,我们看下面的例子:
可是我们这边有两个真正的匹配字符串的开始或者结尾的锚,他们是 \A 和 \Z :
这边还有一个\z(小z),它和\Z不同的是,它不会匹配最后一个回车。:
还可以用\b来匹配单词的边界,或者\B匹配一个不是单词边界的位置..
4 使用量词符号
正则表达式中很大的一部分就是表示可选的字符和字符串重复.一个字符后面跟着一个问号,代表这个字符可以是1个或者0个:
我们可以使用+来匹配一个或者多个字符:
另外一个经常使用的匹配模式是,匹配0个或者多个,我们可以使用+和?的组合来实现:
但是这里有一个更好的办法,那就是*号:
如果我们相匹配一个U.S. Social Security Number,我可以这样做:
逗号分隔符还可以被放进{},比如{start,end},其中start指的是最少的重复次数,end指的是最大的重复字数,其中start和end都是可选的,可是两个必须存在一个:
正则表达式的专用术语都是充满了人性化,比如greedy, reluctant, lazy, and possessive.
思索下面的代码,一个字符串
"Where the", 可是经常会匹配到一个更大的子字符串"Where the sea meets the" 。:
为什么会这样子呢?这是由于*是一个greedy匹配,也就是一个贪婪匹配,他总是匹配,他所能匹配的最长的字符串,如果我们要匹配"Where the",则我们可以这么做:
这边给* 后面加一个?就会生成一个非贪婪的匹配,这条规则对+和{m,n} 都是一样成立的,甚至对?他自己。
这边作者举不出{m,n}?和??的例子,说谁有好的例子可以告诉他..
5 Positive and Negative Lookahead(这个我也不知道怎么翻译...)
这个我觉得 Mastering.Regular.Expressions,讲的更好,我就按自己理解的说了:
这边有两个符号,一个是Positive lookahead也就是(?= ),还有一个Negative lookahead
也就是(?! )。这两个符号其实很容易理解,两个匹配的都是一个分界,而不是其他的,其中(?= )匹配的是括号里面字符的前面所匹配的那个点,比如 s="abc" (?=bc)匹配的就是a和bc之间的那个点. 而(! )恰恰相反,也就是非那个点。。
6 访问后引用
每一个小括号里面的正则表达式都会有它自己的一个子匹配,他们能通过一些方法来得到这些子匹配,比如全局的变量 $1,$2等等。。:
作者这里说象在sub,gsub方法里面$1之类的不能用,我的ruby是1.9 ,sub和gsub是可以用的:
在sub和gsub方法中我们还可以使用\1 ..来替代$1:
注意我们这里使用的是单引号,这是因为双引号会把\1转义,如果要在双引号中使用\1,我们必须用\\1来替代:
在上面的例子中第二个匹配打印出来的是第三个,而第三个匹配,却是nil,注意,这边第二个括号,我们使用的是(?: )这个符号,这个会不捕捉他所匹配的子字符串,所以这里b45没有被打印出来.
$1这种标记虽然有时候看起来很好用,可是我们可以使用更面向对象一点的方,Regexp.match方法这个方法返回一个MatchData类,它包含所有的子匹配,我们可以把它转换成一个数组来取得所有的子匹配:
我们还可以使用begin和end方法,来返回匹配的位移:
而offset方法返回一个2个元素的数组他分别是开始和结束的偏移量:
pre_match 和post_match方法返回当前匹配的前一个前面部分和后面部分.
刚好去除掉匹配的东西,留下的就是我们打印出来的..
1编译正则表达式:
正则表达式能够使用Regexp.compile 方法进行编译(这个方法同Regexp.new方法是同义的),
参数可以是一个字符串或者一个正则式(这边要注意一个问题,如果参数是正则式的话,他所附带的参数将会被传播,你可以不用指定后续的第二个参数,这个马上就会看到),看下面的例子:
test1=Regexp.compile("Bar"); test=Regexp.compile(/Bar/i); #忽略大小写 puts test1.match("bar") #nil puts test.match("bar") #bar
第二个参数,如果存在的话可以是由||连接起来的 下面几个值Regexp::EXTENDED, Regexp::IGNORECASE, Regexp::MULTILINE。第二个参数如果是true代表大小写不敏感,否则代表大小写敏感。可是如果参数是一个正则式的话,第二个参数将会被忽略.
options = Regexp::MULTILINE || Regexp::IGNORECASE pat3 = Regexp.compile("^foo", true) pat4 = Regexp.compile(/Bar/, Regexp::IGNORECASE) puts pat3.match("Doo") #这边大小写不敏感,所以返回doo puts pat4.match("bar") #这边将会返回nil,因为第二个参数被忽略了,ruby解释器会给你提醒的..
第三个参数启用对正则表达式的多字节支持。同样的如果使用正则式,它将会被忽略.
"N" or "n" means None "E" or "e" means EUC "S" or "s" means Shift-JIS "U" or "u" means UTF-8
最后,我们还可以直接使用//来定义正则表达式,而不需要任何compile方法。。
pat1 = /^foo.*/ pat2 = /bar$/i
2 转义特殊字符
我们可以使用Regexp.escape 方法来转义特殊字符,转义的返回值就是所能匹配的正则表达式,也就是说 Regexp.new(Regexp.escape(str)) =~str一定返回true.
str1 = "[*?]" str2 = Regexp.escape(str1) # "\[\*\?\]" puts str1 =~Regexp.new(str2) #返回0
3使用锚
一个锚是一个特殊的匹配一个字符串中的位置的表达式。
最简单的锚就是 ^和$,它们分别匹配一个字符串的开始或者结尾的位置.
strings = "abcXdefXghi" puts strings =~/def/ #4 puts strings =~/abc/ # 0 puts strings =~/ghi/ # 8 puts strings =~/^def/ # nil puts strings =~/def$/ # nil puts strings =~/^abc/ # 0 puts strings =~/ghi$/ # 8
可是这边小小的撒了个谎,其实^和$并不是真正的匹配字符串的开始或结尾,它们会分隔多行,也就是说如果有多行的话,他们会匹配多个开始和结尾,我们看下面的例子:
strings = "abc\ndef\nghi" #这边我们加入了几个回车 puts strings =~/def/ #4 puts strings =~/abc/ # 0 puts strings =~/ghi/ # 8 puts strings =~/^def/ # 4 #它会把新的一行的第一个字符匹配 puts strings =~/def$/ # 4 puts strings =~/^abc/ # 0 puts strings =~/ghi$/ # 8
可是我们这边有两个真正的匹配字符串的开始或者结尾的锚,他们是 \A 和 \Z :
string = "abc\ndef\nghi" puts string =~/\Adef/ # nil puts string =~/def\Z/ # nil puts string =~/\Aabc/ # 0 puts string =~/ghi\Z/ # 8
这边还有一个\z(小z),它和\Z不同的是,它不会匹配最后一个回车。:
string = "abc\ndef\nghi" puts string =~ /ghi\Z/ # 8 puts string =~/\Aabc/ # 0 puts string =~/ghi\Z/ # 8 puts string =~/ghi\z/ # 8 string << "\n" puts string =~/ghi\z/ # nil #由于有最后一个回车,因此这边不能匹配
还可以用\b来匹配单词的边界,或者\B匹配一个不是单词边界的位置..
str = "this is a test" puts str.gsub(/\b/,"|") # "|this| |is| |a| |test|" puts str.gsub(/\B/,"-") # "t-h-i-s i-s a t-e-s-t"
4 使用量词符号
正则表达式中很大的一部分就是表示可选的字符和字符串重复.一个字符后面跟着一个问号,代表这个字符可以是1个或者0个:
pattern = /ax?b/ pat2 = /a[xy]?b/ puts "ab" =~pattern # 0 puts "acb" =~pattern # nil puts "axb" =~ pattern # 0 puts "ayb" =~pat2 # 0 puts "acb" =~pat2 # nil
我们可以使用+来匹配一个或者多个字符:
pattern = /[0-9]+/ puts pattern =~ "1" # 0 puts pattern =~ "2345678" # 0
另外一个经常使用的匹配模式是,匹配0个或者多个,我们可以使用+和?的组合来实现:
pattern = /Huzzah(!+)?/ # Parentheses are necessary here puts pattern =~ "Huzzah" # 0 puts pattern =~ "Huzzah!!!!" # 0
但是这里有一个更好的办法,那就是*号:
pattern = /Huzzah!*/ # * applies only to ! puts pattern =~ "Huzzah" # 0 puts pattern =~ "Huzzah!!!!" # 0
如果我们相匹配一个U.S. Social Security Number,我可以这样做:
ssn = "987-65-4320" pattern = /\d\d\d-\d\d-\d\d\d\d/ puts pattern =~ ssn # 0 #看起来很丑陋,我们其实可以使用更好的方法,那就是使用{}符号,它里面放一个数字#n,代表着一个字符重复n次: pattern = /\d{3}-\d{2}-\d{4}/ puts pattern =~ ssn # 0
逗号分隔符还可以被放进{},比如{start,end},其中start指的是最少的重复次数,end指的是最大的重复字数,其中start和end都是可选的,可是两个必须存在一个:
引用
/x{5}/ # 匹配 5 个x
/x{5,7}/ # 匹配 5到7 个x
/x{,8}/ #匹配 最多8 个x
/x{3,}/ #匹配最少 3个x
/x{5,7}/ # 匹配 5到7 个x
/x{,8}/ #匹配 最多8 个x
/x{3,}/ #匹配最少 3个x
正则表达式的专用术语都是充满了人性化,比如greedy, reluctant, lazy, and possessive.
思索下面的代码,一个字符串
str = "Where the sea meets the moon-blanch'd land,"我们只想匹配
"Where the", 可是经常会匹配到一个更大的子字符串"Where the sea meets the" 。:
str = "Where the sea meets the moon-blanch'd land," match = /.*the/.match(str) puts match[0] # here the sea meets the
为什么会这样子呢?这是由于*是一个greedy匹配,也就是一个贪婪匹配,他总是匹配,他所能匹配的最长的字符串,如果我们要匹配"Where the",则我们可以这么做:
str = "Where the sea meets the moon-blanch'd land," match = /.*?the/.match(str) puts match[0] # "Where the"
这边给* 后面加一个?就会生成一个非贪婪的匹配,这条规则对+和{m,n} 都是一样成立的,甚至对?他自己。
这边作者举不出{m,n}?和??的例子,说谁有好的例子可以告诉他..
5 Positive and Negative Lookahead(这个我也不知道怎么翻译...)
这个我觉得 Mastering.Regular.Expressions,讲的更好,我就按自己理解的说了:
这边有两个符号,一个是Positive lookahead也就是(?= ),还有一个Negative lookahead
也就是(?! )。这两个符号其实很容易理解,两个匹配的都是一个分界,而不是其他的,其中(?= )匹配的是括号里面字符的前面所匹配的那个点,比如 s="abc" (?=bc)匹配的就是a和bc之间的那个点. 而(! )恰恰相反,也就是非那个点。。
reg = /New World(?= Dictionary| Symphony)/ m1 = reg.match(s1) puts m1.to_a[0] # "New World" m2 = reg.match(s2) puts m2.to_a[0] # "New World" m3 = reg.match(s3) puts m3.to_a[0] # nil reg2 = /New World(?! Symphony)/ m1 = reg2.match(s1) puts m1.to_a[0] # "New World" m2 = reg2.match(s2) puts m2.to_a[0] # nil m3 = reg2.match(s3) puts m3.to_a[0] # "New World"
6 访问后引用
每一个小括号里面的正则表达式都会有它自己的一个子匹配,他们能通过一些方法来得到这些子匹配,比如全局的变量 $1,$2等等。。:
str = "a123b45c678" if /(a\d+)(b\d+)(c\d+)/ =~ str puts "Matches are: '#$1', '#$2', '#$3'" # 打印出: Matches are: 'a123', 'b45', 'c768' end
作者这里说象在sub,gsub方法里面$1之类的不能用,我的ruby是1.9 ,sub和gsub是可以用的:
str = "a123b45c678" puts str.sub(/(a\d+)(b\d+)(c\d+)/, "1st=#$1, 2nd=#$2, 3rd=#$3") #打印出1st=a123, 2nd=b45, 3rd=c678
在sub和gsub方法中我们还可以使用\1 ..来替代$1:
str = "a123b45c678" puts str.sub(/(a\d+)(b\d+)(c\d+)/, '1st=\1, 2nd=\2, 3rd=\3') # "1st=a123, 2nd=b45, 3rd=c678"
注意我们这里使用的是单引号,这是因为双引号会把\1转义,如果要在双引号中使用\1,我们必须用\\1来替代:
str = "a123b45c678" puts str.sub(/(a\d+)(?:b\d+)(c\d+)/, "1st=\\1, 2nd=\\2, 3rd=\\3") # "1st=a123, 2nd=c678, 3rd="
在上面的例子中第二个匹配打印出来的是第三个,而第三个匹配,却是nil,注意,这边第二个括号,我们使用的是(?: )这个符号,这个会不捕捉他所匹配的子字符串,所以这里b45没有被打印出来.
$1这种标记虽然有时候看起来很好用,可是我们可以使用更面向对象一点的方,Regexp.match方法这个方法返回一个MatchData类,它包含所有的子匹配,我们可以把它转换成一个数组来取得所有的子匹配:
pat = /(.+[aiu])(.+[aiu])(.+[aiu])(.+[aiu])/i # Four identical groups in this pattern refs = pat.match("Fujiyama") puts refs.to_a.each {|xx| print "#{xx}\n"} # 打印出: ["Fujiyama","Fu","ji","ya","ma"]
我们还可以使用begin和end方法,来返回匹配的位移:
str = "alpha beta gamma delta epsilon" # 0....5....0....5....0....5.... # (for your counting convenience) pat = /(b[^ ]+ )(g[^ ]+ )(d[^ ]+ )/ # Three words, each one a single match refs = pat.match(str) # "beta " puts p1 = refs.begin(1) # 6 返回所经过的位移 puts p2 = refs.end(1) # 11 # "gamma " puts p3 = refs.begin(2) # 11 puts p4 = refs.end(2) # 17 # "delta " puts p5 = refs.begin(3) # 17 puts p6 = refs.end(3) # 23 # "beta gamma delta" puts p7 = refs.begin(0) # 6 puts p8 = refs.end(0) # 23
而offset方法返回一个2个元素的数组他分别是开始和结束的偏移量:
puts range0 = refs.offset(0) # [6,23] puts range1 = refs.offset(1) # [6,11] puts range2 = refs.offset(2) # [11,17] puts range3 = refs.offset(3) # [17,23]
pre_match 和post_match方法返回当前匹配的前一个前面部分和后面部分.
puts before = refs.pre_match # "alpha " puts after = refs.post_match # "epsilon"
刚好去除掉匹配的东西,留下的就是我们打印出来的..
发表评论
-
一个创建闭包的小技巧
2008-06-05 00:12 2134一个小技巧,在Ola Bini 的blog上看到的。 假设你 ... -
解决Colored Cubes问题
2008-06-02 10:43 2785Engineering Puzzle You have fo ... -
ruby1.9中的Iterators
2008-03-05 22:37 3722在ruby1.9中增加了External Iterators这 ... -
一个简单的ruby Metaprogram的例子
2008-03-03 23:49 4104比如下面一个文件 people.txt 引用name,age ... -
Ruby Object Model
2008-03-03 19:29 3576刚好看到,保存一下. -
一个检测方法的参数类型的小程序
2008-03-02 22:48 3249今天没事看blog的时候,看到一个小子实现了这个,不过他的程序 ... -
rails中的BlankSlate源码分析
2008-02-28 23:27 3448其实这个类实现的功能很简单,那就是实现一个没有predefin ... -
ruby中的类变量与类实例变量
2008-02-26 21:15 7636首先,在ruby1.8中类变量是所有子类和父类共享的,可以看下 ... -
在ubuntu上共存多个版本的ruby
2008-02-24 15:20 4377今天装Revactor库的时候,真把我郁闷了,没想到ubunt ... -
看到了一个用ruby写的scheme解释器
2008-02-16 21:35 3771,自己本来想等啥时候有时间做个类似的东西呢,没想到已经有人做 ... -
ruby way之处理RSS和Atom
2008-01-31 01:32 35231 rss 标准库 RSS 是基于xml的,因此你能简单的将 ... -
ruby way之使用REXML解析xml
2008-01-30 00:35 9255REXML 是一个完全用ruby写的processor ,他有 ... -
rails2中的一些被废弃的用法
2008-01-29 00:33 2544这些只是自己最近看web开发敏捷之道的时候(由于书中的版本是1 ... -
ruby way之动态特性之二
2008-01-25 00:49 36801 得到所定义的实体的列表 ruby的反射api能够使我们在 ... -
ruby way之动态特性之一
2008-01-23 01:25 45481 动态的evaluate代码 全局的方法eval 编译并且 ... -
ruby way之高级OOP特性之二
2008-01-20 03:43 29491 把代码像对象一样存储 当你想要以对象的形式存储一块代码的 ... -
ruby way之高级OOP特性之一
2008-01-19 12:14 22661 发送一条消息给一个对象 当你调用一个方法时,你也就是发送 ... -
ruby way之OOP之二
2008-01-16 23:59 23641 理解allocate 在一些特殊的环境中,你可能需要不调 ... -
ruby way之OOP之一
2008-01-16 00:25 26371 使用多个构造方法 在ruby中没有像c++或者ruby中 ... -
ruby way之连接数据库
2008-01-14 00:47 2475这边都只是个大概,具体的要自己去看文档了. 1 连接SQLi ...
相关推荐
3. **正则表达式引擎(Oniguruma)**:介绍了一种新的正则表达式处理引擎,提高了处理效率和灵活性。 4. **国际化(I18N)与消息目录**:探讨了如何使用Ruby进行国际化支持,包括消息目录的创建和管理。 5. **高级...
Ruby的标准库非常丰富,书中会介绍一些常用的库,如Net::HTTP用于网络请求,JSON和YAML用于数据序列化,Regexp用于正则表达式匹配,以及Open3和PTY用于进程管理和交互。这些库大大扩展了Ruby的功能,使其在各种场景...
它覆盖了Ruby的基础语法、类和对象、模块、集合、文件和I/O、网络编程、正则表达式、线程和并发、元编程等方面,以及如何利用Gem进行项目开发。无论是初学者还是有经验的开发者,都能从中受益,提升Ruby编程技能。
它深入探讨了Ruby语言的各种特性,包括基础语法、面向对象编程、模块和类、异常处理、文件系统操作、网络编程以及正则表达式等。书中的例子丰富,旨在帮助读者理解并掌握Ruby的精髓,从而能以"Ruby Way"的方式来思考...
最后,元编程部分将探讨Ruby语言中动态添加方法和属性,以及操作类和模块的能力,这是Ruby作为一种高度动态语言的独特之处。 整个教程不仅提供编程语言的基本知识,还提供了一些编码建议,帮助学习者避免常见错误并...
- **字符串处理**:提供丰富的字符串处理功能,如字符串插值、多行字符串、正则表达式等。 - **异常处理**:支持异常处理机制,能够捕获并处理程序运行时出现的异常情况。 #### 应用领域 - **Web开发**:Ruby最...
更简单的正则表达式,正则表达式是处理字符串的强大工具,这里强调了其在解决特定问题时的简化应用。 #### 42. PHP Solution PHP解决方案,展示了PHP语言在Web开发领域解决问题的能力和灵活性。 #### 43. Another...