正则表达式
最后更新于:2022-04-01 21:07:12
正则表达式比此处所介绍的主题要大得多,确信你理解了这些概念。对于教程, 可以参阅 [perlrequick](http://perldoc.perl.org/perlrequick.html) 或 [perlretut](http://perldoc.perl.org/perlretut.html)。而权威的文档,则能够参阅 [perlre](http://perldoc.perl.org/perlre.html)。
## 匹配和替换返回数量
`m//` 和 `s///` 操作符分别返回匹配或替换的数目。你既可以直接使用该数目, 也可以检查其真值。
~~~
if ( $str =~ /Diggle|Shelley/ ) {
print "We found Pete or Steve!\n";
}
if ( my $n = ($str =~ s/this/that/g) ) {
print qq{Replaced $n occurrence(s) of "this"\n};
}
~~~
## 不要在未检查匹配成功的情况下使用捕获变量
除非匹配成功,捕获变量 `$1` 等是无效的,并且它们不会被清理。
~~~
# BAD: Not checked, but at least it "works".
my $str = 'Perl 101 rocks.';
$str =~ /(\d+)/;
print "Number: $1"; # Prints "Number: 101";
# WORSE: Not checked, and the result is not what you'd expect
$str =~ /(Python|Ruby)/;
print "Language: $1"; # Prints "Language: 101";
~~~
你必须检查匹配的返回值:
~~~
# GOOD: Check the results
my $str = 'Perl 101 rocks.';
if ( $str =~ /(\d+)/ ) {
print "Number: $1"; # Prints "Number: 101";
}
if ( $str =~ /(Python|Ruby)/ ) {
print "Language: $1"; # Never gets here
}
~~~
## 常用匹配选项
### `/i`:不区分大小写
### `/g`:匹配多次
~~~
$var = "match match match";
while ($var =~ /match/g) { $a++; }
print "$a\n"; # prints 3
$a = 0;
$a++ foreach ($var =~ /match/g);
print "$a\n"; # prints 3
~~~
### `/m`:更改 `^` 和 `$` 的意义
正常情况下,`^` 意为字符串的开头,而 `$` 为字符串的结尾。`/m` 使它们分别意为行首和行尾。
~~~
$str = "one\ntwo\nthree";
@a = $str =~ /^\w+/g; # @a = ("one");
@b = $str =~ /^\w+/gm; # @b = ("one","two","three")
~~~
不管是否有 `/m`,使用 `\A` 和 `\z` 来匹配字符串的开头和结尾。`\Z` 除了会忽略最后的换行之外,与 `\z` 相同,
### `/s`:使 `.` 也匹配换行
~~~
$str = "one\ntwo\nthree\n";
$str =~ /^(.{8})/s;
print $1; # prints "one\ntwo\n"
~~~
## 捕获变量 `$1` 及之友
捕获括号对的内容被存储到数字变量中。括号从左到右分配:
~~~
my $str = "abc";
$str =~ /(((a)(b))(c))/;
print "1: $1 2: $2 3: $3 4: $4 5: $5\n";
# prints: 1: abc 2: ab 3: a 4: b 5: c
~~~
捕获括号及变量的数目没有上限。
## 利用 `?:` 避免捕获
如果括号后紧接着 `?:`,那么该分组不会被捕获。在你不想保存匹配的内容时 会有用:
~~~
my $str = "abc";
$str =~ /(?:a(b)c)/;
print "$1\n"; # prints "b"
~~~
## 利用 `/x` 选项使正则表达式更易读
如果你在使用正则表达式时玩了些花样,那么为它写注释。你可以使用 `/x` 选项达到目的。
丑陋的庞然大物:
~~~
my ($num) = $ARGV[0] =~ m/^\+?((?:(? 译注:这里没有考虑到多字节字符。
## 使用 `re => debug` 调试正则表达式
~~~
-Mre=debug
~~~
';