匹配组
你还可以使用正则表达式来匹配一个或多个子字符串。为此,那你应该将正则表达式的一部分放在圆括号之间。这里我有两个组(有时称为’捕获’),第一个尝试匹配字符串 ‘hi’,第二个尝试匹配以 ‘h’ 开头的字符串,后跟任意三个字符(一个点表示’匹配任何一个字符’所以这里的三个点将匹配任何三个连续的字符)并以 ‘o’ 结尾:
/(hi).*(h...o)/ =~ "The word 'hi' is short for 'hello'."
在对正则表达式中的组进行计算之后,将为这些组的匹配值分配等于组数的多个变量。这些变量采用 $
后跟数字的形式:$1
,$2
,$3
等等。执行上面的代码后,我可以像这样访问变量 $1
和 $2
:
print( $1, " ", $2, "\n" ) #=> displays: hi hello
请注意,如果整个正则表达式不匹配,则不会初始化任何组变量。例如,如果 ‘hi’ 在字符串中但 ‘hello’ 不在,则组变量都不会被初始化。两者都是 nil
。
这是另一个示例,它返回三个组,每个组包含一个字符(由点给出)。然后显示组 $1
和 $3
:
/(.)(.)(.)/ =~ "abcdef"
print( $1, " ", $3, "\n" ) #=> displays: a c
这是之前给出的注释匹配程序的新版本(regex3a.rb);现在这已经采用了使用组 (*.)
的值,它返回正则表达式前缀匹配字符串后面的所有字符(零个或更多)(这里是:^\s*#
)。这匹配从当前行(^
)的开头到第一次出现的哈希或磅字符 #
的零个或多个空格(\s*
)字符:
File.foreach( 'regex1.rb' ){ |line|
if line =~ /^\s*#(.*)/ then
puts( $1 )
end
}
最终结果是只匹配第一个可打印字符 #
所在的行;并且 $1
打印出那些行文本减去 #
字符本身之后的文本。我们很快就会看到,这种简单的技术为从 Ruby 文件中提取文档提供了有用的工具。
你不仅仅限于逐字提取和显示字符;你也可以修改文本。此示例显示 Ruby 文件中的文本,但将行注释之前的所有 Ruby 行注释字符('#'
)更改为 C 样式的行注释字符('//'
):
File.foreach( 'regex1.rb' ){ |line|
line = line.sub(/(^\s*)#(.*)/, '\1//\2')
puts( line )
}
在此示例中,使用了 String 类的 sub
方法;它接受一个正则表达式作为它的第一个参数(这里是 /(*\s*)#(.*)/
)和一个替换字符串作为第二个参数(这里是 '\1//\2'
)。替换字符串可能包含编号的占位符,例如 \1
和 \2
,以匹配正则表达式中的任何组 - 此处圆括号之间有两组:(^\s*)
和 (.*)
。sub
方法返回一个新字符串,其中正则表达式所匹配的字符串被替换为替换字符串,而任何未匹配的元素(此处为 #
字符,都会被省略)。