Ruby正则表达式
让我们整理一下做更有趣的程序。这次我们测试一个字符串是否与描述一致,被编码成一个简明的模式。
在这些模式中有些字符和字符联合有特殊的含义,包括:
[] 范围定义 (例如, [a-z] 标志一个字符在a到z的范围中)
\w 字母或者数字; 和 [0-9A-Za-z] 相同
\W 非字母或者数字
\s 空格; 和 [ \t\n\r\f] 相同
\S 非空格字符
\d 数字字符; 和 [0-9] 相同
\D 非数字字符
\b 退格 (0x08) (仅在范围定义中)
\b 单词边界 (如果在非范围定义中)
\B 非单词边界
* 0次或者多次重复
+ 至少一次或者多次重复
{m,n} 最少m次最多n次重复
? 最多重复一次; 同 {0,1}
| 或
() 组
术语“模式(pattern)”是指的正则表达式。在ruby里, 和Perl一样, 它们使用反斜杠"/"括起来而不是使用双引号。如果你以前从来没用过正则表达式, 它们虽然可以做任何事,但是你要知道你需要花费时间来熟悉它。它强大的功能会帮助你解决很多头痛的事,例如匹配、搜索等文本操作。
例如,假设我们想测试一个字符串是否符合情况: "以小写f开头,紧接着是一个大写字符,后面的数量随意,但都是非小写字符。" 如果你是一个有经验的C语言开发者,你可能已经写了很多代码在你的头脑中,是吧?包容它,你几乎不能不能帮助自己。但是在Ruby里,你尽需要使用正则表达式 /^f[A-Z][^a-z]*$/。
如何在<>中包含十六进制数字?没问题。
ruby> def chab(s) # "contains hex in angle brackets"
| (s =~ /<0(x|X)(\d|[a-f]|[A-F])+>/) != nil
| end
nil
ruby> chab "Not this one."
false
ruby> chab "Maybe this? {0x35}" # wrong kind of brackets
false
ruby> chab "Or this? <0x38z7e>" # bogus hex digit
false
ruby> chab "Okay, this: <0xfc0004>."
true
虽然,乍一看,正则表达式容易让人迷惑,你将很快地喜欢上它,因为能够经济地表达自己的意图。
这里有个小程序可以帮助你联系正则表达式。把它存为regx.rb,然后通过在命令行输入"ruby regx.rb"来运行。
# Requires an ANSI terminal!
st = "\033[7m"
en = "\033[m"
puts "Enter an empty string at any time to exit."
while true
print "str> "; STDOUT.flush; str = gets.chop
break if str.empty?
print "pat> "; STDOUT.flush; pat = gets.chop
break if pat.empty?
re = Regexp.new(pat)
puts str.gsub(re,"#{st}\\&#{en}")
end
程序需要输入两次,一次是字符串,一次是正则表达式。字符串被用正则表达式测试,然后用屏幕的反色高亮显示匹配的部分。现在不要太关心细节,很快会有一个这个代码的分析。
str> foobar
pat> ^fo+
foobar
~~~
就像你看到的,"~~~"上字符被高亮显示。
让我们来尝试几个更多的输入。
str> abc012dbcd555
pat> \d
abc012dbcd555
~~~ ~~~
如果那个让你惊讶,参照本页上面的表,\d和字符d是没有关系的,而是匹配一个数字。
如果不止一种情况正确地匹配模式会怎样?
str> foozboozer
pat> f.*z
foozboozer
~~~~~~~~
foozbooz被匹配并用fooz取代,因为一个正则表达式匹配最长的可能的字字符串。
下面是一个模式来分离冒号分割的时间字段。
str> Wed Feb 7 08:58:04 JST 1996
pat> [0-9]+:[0-9]+(:[0-9]+)?
Wed Feb 7 08:58:04 JST 1996
~~~~~~~~
"=~" 是正则表达式的匹配操作符;它返回匹配发现的位置,如果返回nil则表示没有匹配发现。
ruby> "abcdef" =~ /d/
3
ruby> "aaaaaa" =~ /d/
nil
在这些模式中有些字符和字符联合有特殊的含义,包括:
[] 范围定义 (例如, [a-z] 标志一个字符在a到z的范围中)
\w 字母或者数字; 和 [0-9A-Za-z] 相同
\W 非字母或者数字
\s 空格; 和 [ \t\n\r\f] 相同
\S 非空格字符
\d 数字字符; 和 [0-9] 相同
\D 非数字字符
\b 退格 (0x08) (仅在范围定义中)
\b 单词边界 (如果在非范围定义中)
\B 非单词边界
* 0次或者多次重复
+ 至少一次或者多次重复
{m,n} 最少m次最多n次重复
? 最多重复一次; 同 {0,1}
| 或
() 组
术语“模式(pattern)”是指的正则表达式。在ruby里, 和Perl一样, 它们使用反斜杠"/"括起来而不是使用双引号。如果你以前从来没用过正则表达式, 它们虽然可以做任何事,但是你要知道你需要花费时间来熟悉它。它强大的功能会帮助你解决很多头痛的事,例如匹配、搜索等文本操作。
例如,假设我们想测试一个字符串是否符合情况: "以小写f开头,紧接着是一个大写字符,后面的数量随意,但都是非小写字符。" 如果你是一个有经验的C语言开发者,你可能已经写了很多代码在你的头脑中,是吧?包容它,你几乎不能不能帮助自己。但是在Ruby里,你尽需要使用正则表达式 /^f[A-Z][^a-z]*$/。
如何在<>中包含十六进制数字?没问题。
ruby> def chab(s) # "contains hex in angle brackets"
| (s =~ /<0(x|X)(\d|[a-f]|[A-F])+>/) != nil
| end
nil
ruby> chab "Not this one."
false
ruby> chab "Maybe this? {0x35}" # wrong kind of brackets
false
ruby> chab "Or this? <0x38z7e>" # bogus hex digit
false
ruby> chab "Okay, this: <0xfc0004>."
true
虽然,乍一看,正则表达式容易让人迷惑,你将很快地喜欢上它,因为能够经济地表达自己的意图。
这里有个小程序可以帮助你联系正则表达式。把它存为regx.rb,然后通过在命令行输入"ruby regx.rb"来运行。
# Requires an ANSI terminal!
st = "\033[7m"
en = "\033[m"
puts "Enter an empty string at any time to exit."
while true
print "str> "; STDOUT.flush; str = gets.chop
break if str.empty?
print "pat> "; STDOUT.flush; pat = gets.chop
break if pat.empty?
re = Regexp.new(pat)
puts str.gsub(re,"#{st}\\&#{en}")
end
程序需要输入两次,一次是字符串,一次是正则表达式。字符串被用正则表达式测试,然后用屏幕的反色高亮显示匹配的部分。现在不要太关心细节,很快会有一个这个代码的分析。
str> foobar
pat> ^fo+
foobar
~~~
就像你看到的,"~~~"上字符被高亮显示。
让我们来尝试几个更多的输入。
str> abc012dbcd555
pat> \d
abc012dbcd555
~~~ ~~~
如果那个让你惊讶,参照本页上面的表,\d和字符d是没有关系的,而是匹配一个数字。
如果不止一种情况正确地匹配模式会怎样?
str> foozboozer
pat> f.*z
foozboozer
~~~~~~~~
foozbooz被匹配并用fooz取代,因为一个正则表达式匹配最长的可能的字字符串。
下面是一个模式来分离冒号分割的时间字段。
str> Wed Feb 7 08:58:04 JST 1996
pat> [0-9]+:[0-9]+(:[0-9]+)?
Wed Feb 7 08:58:04 JST 1996
~~~~~~~~
"=~" 是正则表达式的匹配操作符;它返回匹配发现的位置,如果返回nil则表示没有匹配发现。
ruby> "abcdef" =~ /d/
3
ruby> "aaaaaa" =~ /d/
nil
