进行匹配
最简单的正则表达式(regular expression)几乎是一系列字符,例如 ‘abc’,你会感觉到它是一个字符串。只需简单的将这些字母放在两个正斜杠(forward-slash)分隔符之间 /abc/
,就可以创建匹配 ‘abc’ 的正则表达式。你可以使用 =〜
运算符方法来测试匹配(match),如下所示:
puts( /abc/ =~ 'abc' ) #=> returns 0
如果匹配,则返回表示字符串中字符位置的整数。如果不匹配,则返回 nil
。
puts( /abc/ =~ 'xyzabcxyzabc' ) #=> returns 3
puts( /abc/ =~ 'xycab' ) #=> returns nil
你还可以在方括号之间指定一组字符,在这种情况下,将在字符串中匹配这组字符中的任何一个。例如,在这里,首先匹配到了 ‘c’,并返回该字符在字符串中的位置:
puts( /[abc]/ =~ 'xycba' ) #=> returns 2
虽然我在上面的示例中使用了正斜杠分隔符,但还有其它方式可以定义正则表达式:你可以专门创建一个使用字符串初始化的新的 Regexp 对象,或者你可以在正则表达式之前使用 %r
并使用自定义分隔符 - 非字母数字字符 - 就像字符串一样(参见第 3 章)。在下面的示例中,我使用花括号分隔符:
regex1 = Regexp.new('^[a-z]*$')
regex2 = /^[a-z]*$/
regex3 = %r{^[a-z]*$}
上面的每一个,都定义了一个匹配全小写字符串的正则表达式(我将很快解释表达式的细节)。 这些表达式可用于测试这样的字符串:
def test( aStr, aRegEx )
if aRegEx =~ aStr then
puts( "All lower case" )
else
puts( "Not all lower case" )
end
end
test( "hello", regex1 ) #=> matches: "All lower case"
test( "hello", regex2 ) #=> matches: "All lower case"
test( "Hello", regex3 ) #=> no match: "Not all lower case"
要测试匹配(match),可以使用 if
和 =〜
运算符:
if /def/ =~ 'abcdef'
如果匹配,则上面的表达式求值为 true(并返回一个整数);如果没有匹配则会计算为 false(并返回 nil
):
RegEx = /def/
Str1 = 'abcdef'
Str2 = 'ghijkl'
if RegEx =~ Str1 then
puts( 'true' )
else
puts( 'false' )
end #=> displays: true
if RegEx =~ Str2 then
puts( 'true' )
else
puts( 'false' )
end #=> displays: false
通常,尝试从字符串的最开头匹配某个表达式是有用的;字符 ^
后跟匹配项用于指定这个(前缀匹配)。从字符串的末尾进行匹配也可能很有用;字符 $
前置一个匹配项用于指定这个(后缀匹配)。
puts( /^a/ =~ 'abc' ) #=> returns 0
puts( /^b/ =~ 'abc' ) #=> returns nil
puts( /c$/ =~ 'abc' ) #=> returns 2
puts( /b$/ =~ 'abc' ) #=> returns nil
当字符串构成更复杂模式(pattern)的一部分时,从字符串的开头或结尾进行匹配会变得更有用。通常,这种模式会尝试匹配指定模式的零个或多个实例。*
字符用于表示其所遵循的模式的零个或多个匹配(matches)。形式上,这被称为“量词”(quantifier)。思考这个示例:
puts( /^[a-z 0-9]*$/ =~ 'well hello 123' )
这里,正则表达式在方括号之间指定了字符范围。此范围包括所有小写字符,a-z,所有数字,0-9,加上空白字符(即此表达式中 “z” 和 “0” 之间的空格)。^
字符表示必须从字符串的开头进行匹配,范围之后的 *
表示必须与范围中的字符进行零次或多次匹配,而 $
字符表示必须匹配到字符串的末尾。换句话说,此模式(pattern)仅匹配从字符串的起始位置到结尾处包含小写字符,数字和空格的字符串:
puts( /^[a-z 0-9]*$/ =~ 'well hello 123' ) # match at 0
puts( /^[a-z 0-9]*$/ =~ 'Well hello 123' ) # no match due to ^ and uppercase 'W'
实际上,这个模式也会匹配一个空字符串,因为 *
表示可以接受零个或多个匹配:
puts( /^[a-z 0-9]*$/ =~ '' ) # this matches!
如果要排除空字符串,请使用 +
(以匹配模式的一个或多个匹配项):
puts( /^[a-z 0-9]+$/ =~ '' ) # no match
尝试使用 start_end2.rb 中的代码,了解更多示例,其中 ^
,$
,*
和 +
可以与范围组合以创建各种不同的匹配模式(match-patterns)。
你可以使用这些技术来确定字符串的特定特征,例如给定字符串是大写的,小写的还是大小写混合的:
aStr = "HELLO WORLD"
case aStr
when /^[a-z 0-9]*$/
puts( "Lower case" )
when /^[A-Z 0-9]*$/
puts( "Upper case" )
else
puts( "Mixed case\n" )
end
通常,正则表达式用于处理磁盘上文件中的文本。例如,假设你希望在 Ruby 文件中显示所有单行(full-line)注释,但省略所有代码或行内注释。你可以通过尝试从每行的开头匹配(^
)零个或多个空格字符(空格字符由 \s
表示)直到注释字符('#'
):
# displays all the full-line comments in a Ruby file
File.foreach( 'regex1.rb' ){ |line|
if line =~ /^\s*#/ then
puts( line )
end
}