2.1.2 Side Effects of a Successful Match
我们再升级上一个程序,使之能够摄氏和华氏相互转换。
在这儿之前,我们需要温习一下MatchVariables。
我们曾经在正则中使用过小括号,使用小括号是由于它可以将正则的某一部分组合起来。同时小括号也会正则分配新的内存块。这些内存含有小括号中的正则所匹配的字符串。如果有不止一对小括号,那就不止一块内存块。每一个内存块内有一段字符串,而非正则的一部分。
由于这些变量含有字符串,那它们是标量变量:在Perl中,它们具有像$1, $2这样的名字。变量个数同正则中小括号对数的个数是相同的。如$4是指第四对小括号所匹配的字符串。
例如:
$_ = “Hello there, neighbor”;
if (/(\S+)(\S+),(\S+)/) {
print “words were $1 $2 $3”;
}
注这和后引用(backreference)\1,\2,\3 在正则匹配中引用字符的字符串相同。但它们不仅是同一事物的两个不同名字;\1,\2,\3是正则正在匹配是引用的;而$1,$2,$3是正则匹配完成后再引用的。想了解更多的关于backreference的信息,可参见perlretut的帮助手册。
执行:
$man perlretut
Backreferences
Closely associated with the matching variables $1, $2, ... are the backreferences
"\1", "\2",... Backreferences are simply matching variables that can be used
inside a regexp. This is a really nice feature -- what matches later in a regexp
is made to depend on what matched earlier in the regexp. Suppose we wanted to look
for doubled words in a text, like 'the the'. The following regexp finds all
3-letter doubles with a space in between:
/\b(\w\w\w)\s\1\b/;
The grouping assigns a value to \1, so that the same 3 letter sequence is used for
both parts.
A similar task is to find words consisting of two identical parts:
% simple_grep '^(\w\w\w\w|\w\w\w|\w\w|\w)\1
/usr/dict/words beriberi booboo coco mama murmur papa The regexp has a single grouping which considers 4-letter combinations, then 3-letter combinations, etc., and uses "\1" to look for a repeat. Although $1 and "\1" represent the same thing, care should be taken to use matched variables $1, $2,... only outside a regexp and backreferences "\1", "\2",... only inside a regexp; not doing so may lead to surprising and unsatisfactory results.
言归正传,请看匹配摄氏和华氏的正则:
![](http://hi.csdn.net/attachment/201202/3/0_1328256134qRpO.gif)
我们把输入的数字放在$1中。
把摄氏或华氏的简称(C或F)放在$2中。
其流程图为:
代码如下:
#! /usr/bin/perl -w
# Mastering Regular Expressiona: Chapter 2 Section 2.
# second program
print "Enter a temperature (e.g., 32F, 100C):\n";
$input = <STDIN>;
chomp($input);
if ($input =~ /^([-+]?[0-9]+)([CF]$)/) {
$inputNum = $1; # Save to named variables to make the ...
$type = $2; # ... rest of the program easier to read.
if ($type eq "C") {
# The input was Celius, so calculate Fahrenheit
$celsius = $inputNum;
$fahrenheit = ($celsius * 9 / 5) + 32;
}
else {
# If not "C", it must be an "F", so calculate Celsius
$fahrenheit = $inputNum;
$celsius = ($fahrenheit - 32) * 5 / 9;
}
# At this point we have both temperatures, so display the results:
printf "%.2f C is %.2f F\n", $celsius, $fahrenheit;
}
else {
# The initial regex did not match, so issue a warning.
print "Expecting a number followed by \"C\" or \"F\", \n";
print "so I don't understand \"$input\".\n";
}