淘先锋技术网

首页 1 2 3 4 5 6 7

相关阅读

Perl:什么是其特有的autovivafacation性质?

Perl:匿名数组嵌套的解引用相关问题

Perl:命令行参数的处理


  1. 前言

正则表达式(Regular Expression),换一种叫法也是规则的表达式,最早追溯到了20世纪50年代,一位美国数学家,斯蒂芬·科尔·克莱尼(Stephen Cole Kleene),发明了规则的语言(Regular Language)的定义,而规则的表达式则是用来描述规则的语言的表达式。肯尼斯·蓝·汤普森(Kenneth Lane Thompson),没错,就是那位发明了UNIX的专家,他借用了这个概念,将其应用到了UNIX上的ed和grep。ed是一个文本编辑器,虽然现在很少有人会用了,但它的正则表达式基因进入了后起之秀vi和vim之中。grep是UNIX/Linux的常用命令,它的名字来源于Globally search a Regular Expression and Print的缩写,功能是查找符合某种规则的表达式。但这时的正则表达式的语法比较难看,这促使拉里·沃尔(Larry Wall)发明了一门语言——Perl,他和Perl社区一起增强了Perl语言的正则表达式功能,直到Perl 5发布,其中内建的正则表达式功能已经登峰造极,成为了Perl最引人注目的特性。

Perl内建的正则表达式引擎可以根据你给出的模式(pattern)串,与主串进行匹配,并且还可以捕获(capture)和替换(replace)等功能。具体来说,正则表达式处理的对象一般为字符串,它可以完成以下功能:

  1. 确认模式串是否匹配了主串。

  1. 把模式串匹配的内容捕获出来。

  1. 把模式串匹配的内容替换成指定的内容。

  1. 匹配的基本过程

Perl提供了一个专门的操作符=~来进行匹配、捕获和替换,操作符的左侧是待匹配的字符串即主串,右侧则是模式串,模式串一般使用一对斜杠/.../包围,且模式串无需使用""包围。如下所示:

$string=~/regular expression/

可以通过一个简单的例子来看一看匹配的过程。

my $str1 = "aAcABC" ;
if ( $str1 =~ /AB/ ) {
  print "match\n" ;
}
else {
  print "unmatch\n" ;
}
exit 0;

以上代码的输出是match。我们来看看第三行作为if条件表达式的模式匹配是如何进行的。首先将主串和模式串左边对齐,即

$str1

a

A

c

A

B

C

/AB/

A

B

我们发现此时模式串与主串不匹配,接着将模式串向右平移一个字符,即

$str1

a

A

c

A

B

C

/AB/

A

B

模式串中的A与主串中的A匹配,但模式串中的B与主串中的c不匹配,将模式串向右平移一个字符,即

$str1

a

A

c

A

B

C

/AB/

A

B

模式串中的A与主串中的c不匹配,将模式串向右平移一个字符,即

$str1

a

A

c

A

B

C

/AB/

A

B

此时匹配成功,匹配表达式返回匹配成功的数量1,即真;如果没有匹配成功,则返回0。

$string=~/regular expression/实际上是简写形式,完整的是$string=~m/regular expression/,其中m表示match(匹配)。

如果使用完整形式,模式串的界定符//,可以换成成对的括号:

$string=~m(regular expression)

$string=~m[regular expression]

$string=~m{regular expression}

$string=~m<regular expression>

甚至可以是其他字符,但需要保证首尾使用相同的字符,如:

$string=~m!regular expression!

$string=~m^regular expression^

$string=~m?regular expression?

  1. 匹配

本节分几个小节介绍了正则表达式的模式匹配功能,即判断模式串是否匹配主串。

本章只包含ASCII字符集中的可见字符和空白字符,包括普通空格(space)、水平制表符(tab)和换行符(\n),不包括其他不可见字符。

3.1 普通字符

大多数字符没有特殊含义,在模式串中表示自身本意,如数字、英文字母和下划线等。

"A"=~/A/ #match

"100"=~/0100/ #match

"B"=~/b/ #unmatch

3.2元字符

Perl中有12个特殊字符,在模式串中有特殊含义,常被称为元字符(meta character),列表如下:

*

+

.

(

)

[

{

^

$

|

\

下面依次介绍这12个元字符。

星号*

*表示其左侧的字符(或字符组)可以有任意数量,零或任意多个,由()或者[]包围的字符集合就是字符组。下表是一些*的例子。

模式串

匹配的字符串

不匹配的字符串

/B*/

任意字符串,包括空串(因为模式串可以是空串)

/AB*/

A、AB、ABB、ABBB......

C、D、BA......

加号+

表示其左侧的字符(或字符组)可以有一个或任意多个。下表是一些+的例子。

模式串

匹配的字符串

不匹配的字符串

/B+/

B、BA、BB、BBA、BBB、BBBA......

A、AB、AD......

/AB+/

AB、ABB、ABBB、BAB、BABB......

C、D、AA、BA......

在默认情况下,+*会优先匹配更多的字符串,即贪婪匹配。举个例子/B+/默认优先尝试在主串中匹配BBB然后才是BB,这在之后的捕获中很重要。

问号?

表示其左侧的字符(或字符组)可以有零个或一个。下表是一些?的例子。

模式串

匹配的字符串

不匹配的字符串

/B?/

任意字符串,包括空串(因为模式串可以是空串)

/AB?/

AB、A、BA、BAB......

C、D、AA、BA......

大括号{}

其中可以有两个数字,由逗号分隔,左边的数字小,右边的数字大,表示其左侧的字符(或字符组)的数量区间,且区间包括两侧的数字(闭区间);或者只有单侧的数字和逗号,{,n}表示0到n的闭区间,{n,}表示大于等于n;或者其中只有一个数字(无逗号),表示确切数量。下表是一些{}的例子。

模式串

匹配的字符串

不匹配的字符串

/AB{3,4}C/

ABBBC、ABBBBC......

AC、ABC、ABBC、ABBBBBC......

/AB{,2}C/

AC、ABC、ABBC、BABBC......

ABBBC、BABBBC......

/AB{2,}C/

ABBC、ABBBC、ABBBBC......

ABC、AC、BABC......

/AB{3}C/

ABBBC、BABBBC、AABBBC......

ABBBBC、ABBC、BABBC......

我们可以看到,{}和*、+、?有对应关系,如下表所示。

元字符

等价关系

*

{0,}

+

{1,}

?

{0,1}

我们之前介绍的都是单字符的重复,也提到了字符组这个东西,圆括号()就有分组的功能,它还是捕获的元字符,本节我们介绍前者,捕获的内容留到后面再说。

圆括号()

表示其间的所有字符是一个整体(字符组)。如果想要在字符组中包括(或),需要在之前加反斜杠\转义。下表是一些()的例子。

模式串

匹配的字符串

不匹配的字符串

/(ABC)+/

ABC、ABCABC、ABCABCABC

AABBCC、BAC......

/A(ABC)+/

AABC、AABCABC......

AAC、AAB......

方括号[]

主要有两种用法:

  1. 表示其间的一个和多个字符作为一个可选的字符组,匹配其中任何一个字符即可(注意,这里也是从左往右在字符组里面尝试)。

模式串

匹配的字符串

不匹配的字符串

/[Ww]ord/

Word、word......

Cord、ord......

如果想要在字符组中包含[或者]本身,需要在之前加反斜杠\转义。

模式串

匹配的字符串

不匹配的字符串

/A[b\[c]D/

AbD、A[D、AcD......

AD、AAD......

/A[b\]c]D/

AbD、A]D、AcD......

AD、AAD......

字符组还可以使用-指定范围,用来便捷的包括一个字符集,如[0-9]表示任意一个数字,[a-z]表示所有小写字母(其实这里是指定了ASCII码的范围)。如果想要在字符组中包含-,可以将其放在[]内的最左侧,即第一个字符,或者最右侧,即最后一个字符。

模式串

匹配的字符串

不匹配的字符串

/A[0-9]D/

A0D、A1D、A2D......

AXD、A99D......

/A[-bB]D/

A-D、AbD、ABD......

AD、AAD......

  1. 如果[]内的第一个字符是^,[^...]表示出了...以外的字符组成的字符组。

模式串

匹配的字符串

不匹配的字符串

/A[^cd]D/

AbD、A1D、A2D......

AcD、AdD......

本小节开始时,我们知道了12个元字符,其中并不包括]和}这两个右括号。所以,如果想单独匹配(注意,这里指}不在一对大括号内,]不在一对中括号内,如果在则仍需要反斜杠\转义)]或},直接输入他们即可。

模式串

匹配的字符串

不匹配的字符串

/A]B/

A]B......

AB、A[D......

/A}B/

A}B......

AB、A{D......

竖线|

表示其两侧的字符(字符组),二选一匹配其中一个即可(两侧从左向右检索))下表是一些|的例子。

模式串

匹配的字符串

不匹配的字符串

/a|b/

a、b、aa、bb......

c、d......

/worda|wordb/

worda、wordb、aworda、bwordb......

wordc、wordd......

如果还希望在模式中加入更丰富的内容,比如,部分内容是二选一,其他内容是固定的,则需要把可选部分使用圆括号包围,如下表所示。

模式串

匹配的字符串

不匹配的字符串

/Tom and (Jerry|me)/

Tom and Jerry、Tom and me......

Tom and others......

如果想要单字符二选一,可以使用[ab]或(a|b),(a|b)还有捕获功能。

反斜杠\

之前,我们已经见过\了,它的一类功能就是放在原字符前,则会撤销该元字符的特殊功能,使元字符变成一个普通字符,仅匹配自身。下表是一些\的例子。

\放在某些普通字符前,能组成特殊字符(字符组)或有其他含义。这部分内容较多,将放在下一节单独列出。

模式串

匹配的字符串

不匹配的字符串

/ab\*cd/

ab*cd......

abcd、abbcd......

/\(abd\)/

(abc)......

abc......

/ab\\cd/

ab\cd......

abcd......

句点.

.匹配任意一个字符,一般情况下,不匹配换行符\n,除非模式有s修饰符(在之后会介绍修饰符)。下表是一些.的例子。

模式串

匹配的字符串

不匹配的字符串

/abc.e/

abcde、abcfe、"abc e"......

abce、"ac\ne"......

当.在[]中,只匹配.自身,不在匹配任意一个字符。即无需转义字符\,也可匹配.自身。

尖角^

当^出现在模式的开头时,表示匹配字符串的行开头,此时的模式匹配过程使得,在每行内不会尝试将模式串向右移。如果待匹配的字符串只有一行,即中间没有换行符\n,那么^等同于只匹配字符串的开头。下表是一些^的例子。

模式串

匹配的字符串

不匹配的字符串

/^abc/

abc、abcd......

aabc、1abc......

如果待匹配的字符串是多行文本,如:

$str = "this is

an example

of multi-lines";

那么/^this/、/^an/、/^of/都能匹配$str。

另外,当^出现在[]开头时,表示排除^后面的字符而形成的字符组,如果要想字符组中有^,则不要讲其放在[]的开头。

美元符$

当美元符$出现在模式的结尾时,表示匹配字符串的行结尾。如果待匹配的字符串只有一行,即中间没有换行符\n,那么^等同于只匹配字符串的结尾。下表是一些$的例子。

模式串

匹配的字符串

不匹配的字符串

/abc$/

abc、2abc......

abcd、abc2......

/^abc$/

只有abc

除了abc外的所有字符串

如果待匹配的字符串是多行文本,如:

$str = "this is

an example

of multi-lines";

那么/is$/、/example$/、/lines$/都能匹配$str。

$还有一个功能,就是表示一个变量,将变量的值嵌入模式串中。这个功能将在后面介绍。

3.3反斜杠\

鉴于反斜杠\会影响后面字符的含义,且组合较多,我们单独用一节来讨论。

它的功能可以分为三类:

  1. 放在元字符前,撤销该元字符的特殊含义,使元字符仅匹配自身。

  1. 与后续某些字符组合,表示特定字符组,常用的如下表所示。

组合

含义

\d

数字的集合,等价于[0-9]

\D

非数字的集合,等价于[^0-9]

\n

表示换行符

\s

表示空白字符

\S

表示非空白字符

\t

表示水平制表符tab

\w

数字、字母和下划线的集合,等价[_0-9a-zA-Z])

\W

表示除了\所表示的字符以外的字符组,等价于[^_0-9a-zA-Z]

补充说明:在本章开头,已经声明了我们是在ASCII范围内讨论。所以我们简化了一些描述。比如\w还可以匹配非ASCII字符,意思是只有在ASCII字符集内,它才等价于[_0-9a-zA-Z]。其他特殊字符组可能也有类似情况,当应用范围超出ASCII字符集时,请查阅Perl官方文档获得更精确的说明。

  1. 与后续字符组成某类锚位,用来匹配模式的位置,常用的如下表所示。

组合

含义

\A

字符串的开头

\b

“单词”的边界,“单词”由数字、字母和下划线组成。边界指字符串的开头、结尾、"单词”与“非单词”之间的位置(没有宽度,指字符间的位置)

\z

字符串的结尾

\Z

字符串的行结尾,等价于模式串结尾处的$

\b模式的例子如下所示。

模式串

匹配的字符串

不匹配的字符串

/\beat\b/

eat、to eat、eat to

heat、eaten

如果待匹配的字符串是多行文本,如下所示。

$str = "this is

an example

of multi-lines";

下表是几个例子。

模式串

是否匹配$str

模式串

是否匹配$str

/\Athis/

/is\z/

/\Aan/

/lines\Z/

/lines\z/

/is\Z/

3.4修饰符

在模式的尾部/之后,可以添加一些修饰符,调整该模式的匹配功能,如下表所示。

修饰符

含义

模式串

匹配的字符串

i

匹配时不区分大小写

/abc/i

abc、Abc、ABC

s

使句点号.匹配换行符

/a.*b/s

"a\nb"

x

忽略模式中的空白字符

/a b/x

ab

x修饰符会忽略模式中包含的空白字符,使我们可以把很长的模式(可读性差)以(任意数量的)空白(包括换行符)分隔开。

/^[0-9]{4}-.{7,10}-[^-]+-\d{2,5}#8$/

等价于:

/^ [0-9]{4}

-

.{7,10}

-

[^-]+

-

\d{2,5}

#8

$/x

有了修饰符x,我们还可以在模式中添加注释#,进一步提高代码的可读性。

/^ [0-9]{4} # four digital

-

.{7,10} #any string contains 7-10 characters

-

[^-]+ #DO NOT write / here !!!

-

\d{2,5}

#8

$/x

添加注释时,需要注意两点:

  1. 注释中不能出现模式的终止符号,上例中是/。

  1. 如果添加了#注释,那么原先模式中的#,则需要换成\#或者[#]。

还有一个常用的修饰符g,将在后面进行介绍。

3.5内插变量

前面几小节中,模式串的内容都是常量,是不可改变的。如果有很多模式串需要匹配,我们可以在模式串中直接使用变量(注意,变量要加$前缀,这并不会和模式串结尾可能的元字符$混淆)。下面我们看一个例子。

#!/usr/local/bin/perl

my @lines = (
  "China_capital Beijing",
  "China Shanghai",
  "Japan Toyko",
  "USA Newyork",
  "USA_capital DC",
);

my @countries = (
  "China",
  "USA",
);

for my $line ( @lines ) {
  for my $country ( @countries ) {
    if ( $line =~ /$country/ ) {
      print $line, "\n";
    }
  }
}

exit 0;

运行上述代码,得到输出如下:

China_capital Beijing

China_Shanghai

USA Newyork

USA_capital DC

我们直接在模式中书写变量即可,如第18行。

如果我们需要只匹配有首都的行,需要稍作修改,不能想当然地使用

if( $line =~/$country_capital/)

因为Perl解释器无法知道变量名的结尾在哪里,为了精确定义变量名的范围,我们可以使用{},即

if( $line =~/${country}_capital/)

或者也可以引入():

if( $line =~/$country()_capital/)

在上式中,()(中间没有空格)插在变量名的结尾,阻断了Perl试图读取更长的变量名。

在任何可以插入变量的位置,都可以插入数组的元素和散列的值。

有了变量,我们可以匹配的自由度就会提高,但还不够。下一节将会了解正则表达式更强大的功能。

4.分组和捕获

在本节中,我们要学习本章开始时提出的一个功能——把字符串中匹配了模式的内容捕获出来,即分组(grouping)和捕获(capture)。

圆括号完成分组和捕获的功能。

4.1分组并捕获

请先看一个实例。

#!/usr/local/bin/perl

my $str = "module xyz something";
if ( $str =~ /^module\s+(\S+)/ ) {
  print "module name is: ", $1, "\n";
}

exit 0;

运行上述代码,会输出:

modole name is:xyz

模式串 /^module\s+(\S+)/中的^表示匹配开头,module匹配成功后,匹配一个空格,然后匹配三个非空格字符,而且\S+是被()包括,这代表捕获()中的内容。

注意,这里不能写成/^module\s+(\S)+/否则只会捕获z而不是把xyz作为一个整体捕获。

捕获完成了之后,存到哪里呢?Perl内置了9个变量:$1、$2、$3、... 、$9,按照左括号出现的顺序,依次存放9组括号捕获的内容。下面再看一个例子。

#!/usr/local/bin/perl

my $str = "To be or not to be, it’s a question.";
if ($str =~ /^((\S+)\s+(\S+))\s+(\S+)\s+((\S+)\s+(\S+)\s+(\S+))\s+(.+)/) {
  for my $n ( 1..9 ) {
    print "\$$n is: ${$n}\n";
  }
}

exit 0;

运行代码的输出如下:

$1 is: To be

$2 is: To

$3 is: be

$4 is: or

$5 is: not to be,

$6 is: not

$7 is: to

$8 is: be,

$9 is: it’s a question.

如果我们想捕获更多的字符,9个预设的变量就不够了,我们可以把捕获的内容存到一个数组中去。稍加修改,可以得到以下代码。

#!/usr/local/bin/perl

my $str = "To be or not to be, it’s a question.";
my @caps;
if ( @caps = $str =~ /^((\S+)\s+(\S+))\s+
                       (\S+)\s+
                       ((\S+)\s+(\S+)\s+(\S+))\s+
                       ([^.]+)
                       (((.)))
                     /x ) {
  for my $n ( 0..$#caps ) {
    print 1+$n, " is: $caps[$n]\n";
  }
}

exit 0;

运行代码的输出如下:

1 is: To be

2 is: To

3 is: be

4 is: or

5 is: not to be,

6 is: not

7 is: to

8 is: be,

9 is: it’s a question

10 is: .

11 is: .

12 is: .

我们在第5行使用了一个数组@caps,if条件表达式的执行情况是这样的:首先进行正则表达式匹配,然后由于赋值表达式左侧是一个数组(或散列),此时模式匹配处于列表上下文环境中,模式匹配返回捕获的内容(而不是匹配到的数量)。

如果太多的圆括号让你眼花缭乱,我们可以采用命名变量?<>,将?<>放置在捕获圆括号内的最左侧,?<>的尖括号内是名称。

#!/usr/local/bin/perl

my $str = "To be or not to be, it’s a question.";
if ( $str =~ /^(?<first_two_words>(\S+)\s+(?<second_word>\S+))/ ) {
  print "First two words is: $+{'first_two_words'}\n";
  print "Second word     is: $+{'second_word'}\n";
}

exit 0;

代码的输出结果如下所示:

First two words is: To be

Second word is: be

?<>尖括号内的名词是散列%+中的键名。

4.2匹配的特点

模式匹配有两个特点:

  1. 尽可能多地匹配(贪婪匹配)。

  1. 匹配达成后就结束。

我们可以看以下例子。

#!/usr/local/bin/perl
use strict;

my $str = "To be or not to be, it’s a question.";
if ( $str =~ /(.+)/ ) {
  print "Matched is: ", $1, "\n";
}

exit 0;

运行代码会输出:

Matched is: To be or not to be, it’s a question.

将第5行的+换成*,输出结果是一样的,他们都有“贪婪”得特点,尽可能匹配更多的字符。在某些情况下,我们希望它们不要匹配太多字符,留一些给后面的模式串。那么,我们可以后置?来约束+和*,使它们尽量少匹配。

一个例子如下所示。

#!/usr/local/bin/perl
use strict;

my $str = "To be or not to be, it’s a question.";
if ( $str =~ /(.+?)/ ) {
  print "Matched is: ", $1, "\n";
}

exit 0;

运行代码会输出:

Matched is: T

注意,.+?优先匹配一个字符,.*?优先匹配零个字符。

我们再来看看第二个特点。

#!/usr/local/bin/perl
use strict;

my $str = "To be or not to be, it’s a question.";
if ( $str =~ /be(.{4})/ ) {
  print "Matched is: ", $1, "\n";
}

exit 0;

运行代码会输出:

Matched is: or

实际匹配的是“ or ”四个字符(前后各有一个空格)。一旦匹配到了,匹配就会结束,无论后面是否有匹配的可能,都不会尝试继续匹配后面的字符串。如果需要匹配所有的情况,则需要使用之前提到过的g修饰符,并且如果要捕获,则需使用外部数组来接受正则表达式匹配的返回值。如下所示。

#!/usr/local/bin/perl
use strict;
my @caps;
my $str = "To be or not to be, it’s a question.";
if ( @caps = $str =~ /be(.{4})/g ) {
  for my $cap ( @caps ){
    print "Matched is: ", $cap, "\n";
  }
}

exit 0;

运行以上代码会输出:

Matched is: or

Matched is: , it

为什么不能使用内置变量$1和$2呢?因为代码中只有一组圆括号,即便匹配了两次,“ or ”和“, it”也是先后存储至$1,而$2是未被赋值的。

4.3分组不捕获

有时,我们仅使用()分组,而不捕获其中的内容。我们可以使用(?:),如以下所示。

#!/usr/local/bin/perl
use strict;

my $str = "module xyz (something)";
if ( $str =~ /^(?:module)\s+(\S+)/ ) {
  print "module name is: ", $1, "\n";
}

exit 0;

以上代码输出:

module name is: xyz

以上代码的模式串中有两组圆括号,但是第一组采用了(?:)的形式,即仅分组,不捕获。所以$1内存放的是第一对没有?:的圆括号内捕获的内容,即(\S+)。

4.4分组捕获并反向引用

有时,我们希望在模式内部,即刻引用左侧已部分匹配并捕获成功的内容(即反向引用),作为后续匹配的变量。举一个例子,我们要检查一个单词开头的两个字符,如果两个字符一样,那么很有可能是一个错误,将其输出。

#!/usr/local/bin/perl
use strict;
my $str = "To bbe or not to be, it’s a question.";

if ( $str =~ /\b((.)\2\S*)\b/ ) {
  print "Warning: $1\n";
}

exit 0;

运行代码的输出结果如下:

Warning: bbe

模式/\b((.)\2\S*)\b/中的\2是反向引用了第2组圆括号内,即(.)匹配的内容,注意,这里必须使用带有捕获功能的括号。(.)\2组成了两个一样的字符。后面紧跟任意数量的非空白字符。在模式外部,捕获这个疑似出错的单词的是变量$1。不要和内部反向引用变量\1混淆。诸如\1,\2的反向引用变量,一共有且只有9个:\1、\2、......、\9。

如果想反向引用的变量超过9个,则可以使用\g{N},N为数字。如下所示。

#!/usr/local/bin/perl
use strict;
my $str = "1234567800";

if ( $str =~ /(.)(.)(.)(.)(.)(.)(.)(.)((.)\g{10})/ ) {
  print "Warning: $9\n";
}

exit 0;

代码的输出结果如下:

Warning: 00

反向引用\N或\g{N}只能出现在模式内,不能在模式外使用。

5.替换

本节我们将学习本章开始时提出的最后一个功能——把字符串中匹配的内容替换成指定内容。

替换是在模式匹配的基础上,使用s操作符,并在第2个/右侧(即第2组//中)添加替换后的内容,如下所示:

$str =~ s/regular expression/replacement/

替换是把第二个/左侧匹配的所有内容,都替换成右侧的字符串(可以包含变量)。注意,第二组//中的替换内容不是正则表达式,只是字符串。如果匹配和替换成功,则左侧的变量会立刻被改变。

$str = "abcde";

$str =~ s/bcd/BCD/; #now $str is :aBCDe

在替换部分可以加入变量。

$replace = "BCD";

$str = "abcde";

$str =~ s/bcd/$replace/; #now $str is :aBCDe

在替换部分也可以加入左侧模式中分组捕获的内容(因为替换时,模式匹配已经结束):

$str = "abcde";

$str =~ s/(bcd)/$1/; #now $str is: abcde

$str = "abcde";

$str =~ s/(.)/$2$1/; #now $str is: bacde

5.1修饰符

此前介绍的模式匹配的修饰符,都可在s///尾部使用,意义基本相同。比较常用的是使用/g将匹配的内容全部替换。

$str = "abcde abcde";

$str =~ s/bcd/BCD/; #now $str is :aBCDe abcde

$str = "abcde abcde";

$str =~ s/bcd/BCD/g; #now $str is :aBCDe aBCDe

5.2界定符

此前我们介绍过,模式匹配的界定符,除了最常用的//,还可以是其他成对的括号,或者其他字符。在替换中,事实上有两组界定符,他们既可以是相同的:

$str =~ s{regular expression}{replacement}

也可以是不同的:

$str =~ s{regular expression}<replacement>

5.3不改变原变量

如果不希望改变原变量,则需要先复制备份:

$str1 = "abcde abcde";

$str2 = $str1;

$str2 =~ s/bcd/BCD/; #now $str2 is :aBCDe abcde

常简写成:

(str2 = $str1)=~ s/bcd/BCD/

如果不使用括号的话,由于正则匹配的优先级高于赋值,这里又是标量上下文,则会把匹配的数量赋值给$str2。

以上内容来源于《Perl语言IC设计实践》