匹配组

你还可以使用正则表达式来匹配一个或多个子字符串。为此,那你应该将正则表达式的一部分放在圆括号之间。这里我有两个组(有时称为’捕获’),第一个尝试匹配字符串 ‘hi’,第二个尝试匹配以 ‘h’ 开头的字符串,后跟任意三个字符(一个点表示’匹配任何一个字符’所以这里的三个点将匹配任何三个连续的字符)并以 ‘o’ 结尾:

groups.rb
  1. /(hi).*(h...o)/ =~ "The word 'hi' is short for 'hello'."

在对正则表达式中的组进行计算之后,将为这些组的匹配值分配等于组数的多个变量。这些变量采用 $ 后跟数字的形式:$1$2$3 等等。执行上面的代码后,我可以像这样访问变量 $1$2

  1. print( $1, " ", $2, "\n" ) #=> displays: hi hello

请注意,如果整个正则表达式不匹配,则不会初始化任何组变量。例如,如果 ‘hi’ 在字符串中但 ‘hello’ 不在,则组变量都不会被初始化。两者都是 nil

这是另一个示例,它返回三个组,每个组包含一个字符(由点给出)。然后显示组 $1$3

  1. /(.)(.)(.)/ =~ "abcdef"
  2. print( $1, " ", $3, "\n" ) #=> displays: a c

这是之前给出的注释匹配程序的新版本(regex3a.rb);现在这已经采用了使用组 (*.) 的值,它返回正则表达式前缀匹配字符串后面的所有字符(零个或更多)(这里是:^\s*#)。这匹配从当前行(^)的开头到第一次出现的哈希或磅字符 # 的零个或多个空格(\s*)字符:

regex3b.rb
  1. File.foreach( 'regex1.rb' ){ |line|
  2. if line =~ /^\s*#(.*)/ then
  3. puts( $1 )
  4. end
  5. }

最终结果是只匹配第一个可打印字符 # 所在的行;并且 $1 打印出那些行文本减去 # 字符本身之后的文本。我们很快就会看到,这种简单的技术为从 Ruby 文件中提取文档提供了有用的工具。

你不仅仅限于逐字提取和显示字符;你也可以修改文本。此示例显示 Ruby 文件中的文本,但将行注释之前的所有 Ruby 行注释字符('#')更改为 C 样式的行注释字符('//'):

regex4.rb
  1. File.foreach( 'regex1.rb' ){ |line|
  2. line = line.sub(/(^\s*)#(.*)/, '\1//\2')
  3. puts( line )
  4. }

在此示例中,使用了 String 类的 sub 方法;它接受一个正则表达式作为它的第一个参数(这里是 /(*\s*)#(.*)/)和一个替换字符串作为第二个参数(这里是 '\1//\2')。替换字符串可能包含编号的占位符,例如 \1\2,以匹配正则表达式中的任何组 - 此处圆括号之间有两组:(^\s*)(.*)sub 方法返回一个新字符串,其中正则表达式所匹配的字符串被替换为替换字符串,而任何未匹配的元素(此处为 # 字符,都会被省略)。