网名骏马金龙,钟情于IT世界里的各种原理和实现机制,强迫症重症患者。爱研究、爱翻译、爱分享。特借此一亩三分田记录自己成长点滴!!!
我本问道人,道心不坚,必将与道无缘!谨记心中。
目标:将IT技术的研究发展成终身追求,为同在路上或刚上路的道友做一点点贡献(2018)
友情提示:还没找工作的人,请别看我的文章,会让你觉得原来都白学了,从而耽误找工作
博客园
首页
管理
Linux & Shell
MariaDB系列
网站架构系列
Perl系列
Win调整和小技巧
随笔-351 文章-2 评论-549
Perl正则表达式超详细教程
分类: Perl语言
前言
想必学习perl的人,对基础正则表达式都已经熟悉,所以学习perl正则会很轻松。这里我不打算解释基础正则的内容,而是直接介绍基础正则中不具备的但perl支持的功能。关于基础正则表达式的内容,可参阅基础正则表达式。
我第一个要说明的是,perl如何使用正则。还记得当初把《精通正则表达式》的书看了一遍,把perl正则也学了个七七八八,但是学完后却不知道怎么去使用perl正则,虽然里面也介绍了一点如何使用perl语言,grep的"-P"选项使用的也是perl正则,ack工具支持的也完全是perl正则,但都没有完整地体现perl正则的功能,总感觉缺点啥。最大的无奈莫过于此了,学了知识,却不知道怎么完整地应用。所以,我把如何使用perl正则来匹配数据放在最开头介绍,包括匹配指定字符串、匹配变量、匹配标准输入(如管道传递的数据)以及匹配文件中的每一行数据,而且后文我假设各位和我当初一样,完全没有perl语言基础,所以我会介绍一些perl语言和后文相关的语法,确保全文学习过程没有任何阻塞。
另外,本系列只介绍匹配操作,关于内容替换,因为和学习使用perl正则并无多大关系,所以替换相关的将在下一篇文章单独解释。
这里推荐一个学正则非常好的资料:stackflow上关于各种语言(perl/python/.net/java/ruby等等)的正则的解释、示例,这里收集的都是对问题解释的非常清晰且非常经典的回答。在我学习perl正则的时候,对有些功能实在理解不了(想必你也一定会),就会从这里找答案,而它,也从来没让我失望:https://stackoverflow.com/questions/22937618/reference-what-does-this-regex-mean/22944075#22944075
以下是perl正则的man文档:
perl正则快速入门:man perlrequick
perl正则教程:man perlretut
perl正则完整文档:man perlre
学perl正则必备的一点基本语法
新建一个文件作为perl脚本文件,在其首行写上#!/usr/bin/perl,它表示用perl作为本文件的解释器。写入一些perl程序后,再赋予执行权限就可以执行了,或者直接使用perl命令去调用这个脚本文件,前面的两个过程都可以省略,这和shell脚本的方式是完全一样的,无非是将bash替换为了perl,想必各位都理解。
1.print用来输出信息,相当于shell中的echo命令,但需要手动输入换行符"\n"进行换行。
例如:
#!/usr/bin/perl
print "hello world\n"; # 注意每一句后面都使用分号结尾
保存后,执行它(假设脚本文件名为test.pl):
$ chmod +x test.pl
$ perl test.pl
2.变量赋值
perl中的变量可以不用事先声明,可以直接赋值甚至直接引用。注意变量名前面总是需要加上$符号,无论是赋值的时候还是引用的时候,这和其它语言不太一样。
#!/usr/bin/perl
$name="longshuai";
$age=18;
print "$name $age \n";
3.if语句用来判断,语法格式为:
if(condition){
body
}else{
body
}
例如:
$age = 18;
if($age <= 20){
print "age less than 20\n";
} else {
print "age greate than 20\n";
}
4.默认参数变量
在perl中,对于需要参数的函数或表达式,但却没有给参数,这是将会使用perl的默认参数变量$_。
例如,下面的print本来是需要参数的,但是因为没有给参数,print将输出默认的参数变量$_,也就是输出"abcde"。
$_="abcde";
print ;
perl中使用$_的地方非常多,后文还会出现,不过用到的时候我会解释。
5.读取标准输入
perl中使用一对尖括号格式的来读取来自非文件的标准输入,例如来自管道的数据,来自输入重定向的数据或者来自键盘的输入。需要注意的是,读取的输入会自带换行符,所以print输出的时候不要加上额外的换行符。
例如,在test.pl文件中写入如下内容:
#!/usr/bin/perl
$data=;
print "$data";
然后用管道传递一行数据给perl程序:
echo "abcdefg" | perl test.pl
只是需要注意,将赋值给变量时,将只能读取一行(遇到换行符就结束读取)。例如下面的perl将读取不了"hijklmn"。
echo -e "abcdefg\nhijklmn" | perl test.pl
如果想要读取多行标准输入,就不能将其赋值给变量,而是使用foreach来遍历各行(此处不介绍其它方式):
foreach $line (){
print "$line";
}
以上就是foreach的语法:
圆括号中的内容是待遍历对象,通常是一个列表,比如上面用读取的多行数据就是一个列表,每一行都是列表中的一个元素;
$line称为控制变量,foreach在每次迭代过程中都会选中一个列表中的元素赋值给$line,例如将读取的每一行都赋值给$line。
可以省略$line,这时就采用默认的参数变量$_,所以以下两个表达式是等价的:
foreach (){
print "$_";
}
foreach $_ (){
print "$_";
}
6.读取文件中的数据
正则强大的用处就是处理文本数据,所以必须要说明perl如何读取文件数据来做正则匹配。
我们可以将文件作为perl命令行的参数,perl会使用<>去读取这些文件中的内容。
foreach (<>){
print "$_";
}
执行的时候,只要把文件作为perl命令或脚本文件的参数即可:
perl test.pl /etc/passwd
7.去掉行尾分隔符
由于<>和读取文件、读取标准输入的时候总是自带换行符,很多时候这个自带的换行符都会带来格式问题。所以,有必要在每次读取数据时将行尾的换行符去掉,使用chomp即可。
例如:
foreach $line () {
chomp $line;
print "$line read\n";
}
以下是执行结果:
[root@xuexi ~]# echo -e "malongshuai gaoxiaofang" | perl 26.plx
malongshuai gaoxiaofang read
如果上面的例子中不加上chomp,那么执行结果将像下面一样:
[root@xuexi perlapp]# echo -e "malongshuai gaoxiaofang" | perl 26.plx
malongshuai gaoxiaofang
read
显然,输出格式和print语句中期待的输出格式不一样。
前面说过,可以省略$line,让其使用默认的参数变量$_,所以可以这样读取来自perl命令行参数文件的数据:
foreach (<>) {
chomp;
print "$_ read\n";
}
8.命令行的操作模式
其实就是一行式。perl命令行加上"-e"选项,就能在perl命令行中直接写perl表达式,例如:
echo "malongshuai" | perl -e '$name=;print $name;'
因为perl最为人所知的就是它应用了各种符号的组合,让人看着怪异无比,而这些符号放在命令行中很可能会被shell先解析,所以强烈建议"-e"后表达式使用单引号包围,而不是双引号。
更建议,如果可以,不要使用perl命令行的方式,调试起来容易混乱。
perl如何使用正则进行匹配
使用=~符号表示要用右边的正则表达式对左边的数据进行匹配。正则表达式的书写方式为m//。关于m//,其中斜线可以替换为其它符号,规则如下:
双斜线可以替换为任意其它对应符号,例如对称的括号类,m(),m{},相同的标点类,m!!,m%%等等
只有当m模式采用双斜线的时候,可以省略m字母,即//等价于m//
如果正则表达式中出现了和分隔符相同的字符,可以转义表达式中的符号,但更建议换分隔符,例如/http:\/\//转换成m%http://%
所以要匹配内容,有以下两种方式:
方式一:使用data =~ m/reg/,可以明确指定要对data对应的内容进行正则匹配
方式二:直接/reg/,因为省略了参数,所以使用默认参数变量,它等价于$_ =~ m/reg/,也就是对$_保存的内容进行正则匹配
perl中匹配操作返回的是匹配成功与否,成功则返回真,匹配不成功则返回假。当然,perl提供了特殊变量允许访问匹配到的内容,甚至匹配内容之前的数据、匹配内容之后的数据都提供了相关变量以便访问。见下面的示例。
例如:
1.匹配给定字符串内容
$name = "hello gaoxiaofang";
if ($name =~ m/gao/){
print "matched\n";
}
或者,直接将字符串拿来匹配:
"hello gaoxiaofang" =~ m/gao/;
2.匹配来自管道的每一行内容,匹配成功的行则输出
foreach (){
chomp;
if (/gao/){
print "$_ was matched 'gao'\n";
}
}
上面使用了默认的参数变量$_,它表示foreach迭代的每一行数据;上面还简写的正则匹配方式/gao/,它等价于$_ =~ m/gao/。
以下是执行结果:
[root@xuexi perlapp]# echo -e "malongshuai gaoxiaofang" | perl 26.plx
malongshuai gaoxiaofang was matched 'gao'
3.匹配文件中每行数据
foreach (<>){
chomp;
if(/gao/){
print "$_ was matched 'gao'\n";
}
}
4.如果想要输出匹配到的内容,可以使用特殊变量$&来引用匹配到的内容,还可以使用$`引用匹配前面部分的内容,$'引用匹配后面部分的内容
例如:
aAbBcC =~ /bB/
由于匹配的内容是bB,匹配内容之前的部分是aA,匹配之后的部分是cC,于是可以看作下面对应关系:
(aA)(bB)(cC)
| | |
$` $& $'
以下是使用这三个特殊变量的示例:
$name="aAbBcC";
if(/bB/){
print "pre match: $` \n";
print "match: $& \n";
print "post match: $' \n";
}
需要注意的是,正则中一般都提供全局匹配的功能,perl中使用修饰符/g开启。当开启了全局匹配功能,这3个变量保存的值需要使用循环语句去遍历,否则将只保存第一次匹配的内容。例如:
$name="aAbBcCbB";
if(/bB/g){ # 匹配完第一个bB就结束
print "pre match: $` \n";
print "match: $& \n";
print "post match: $' \n";
}
while(/bB/g){ # 将迭代两次
print "pre match: $` \n";
print "match: $& \n";
print "post match: $' \n";
}
perl支持的正则
从这里开始,正式介绍perl支持的正则。
出于方便,我全部都直接在perl程序内部定义待匹配的内容,如果想要匹配管道传递的输入,或者匹配文件数据,请看上文获取操作方法。
为了完整性,每一节中我都是先把一大堆的内容列出来做个简单介绍,然后再用示例解释每个(或某几个)。但perl正则的内容太多,而且很多功能前后关联,所以如果列出来的内容没有在同一小节内介绍,那么就是在后面需要的地方介绍。当然,也有些没什么用或者用的很少的功能(比如unicode相关的),通篇都不会介绍。
模式匹配修饰符
指定模式匹配的修饰符,可以改变正则表达式的匹配行为。例如,下面的i就是一种修饰符,它让前面的正则REG匹配时忽略大小写。
m/REG/i
perl总共支持以下几种修饰符:msixpodualngc
i:匹配时忽略大小写
g:全局匹配,默认情况下,正则表达式"abc"匹配"abcdabc"字符串的时候,将之匹配左边的abc,使用g将匹配两个"abc"
c:在开启g的情况下,如果匹配失败,将不重置搜索位置
m:多行匹配模式
s:让.可以匹配换行符"\n",也就是说该修饰符让.真的可以匹配任意字符
x:允许正则表达式使用空白符号,免得让整个表达式难读难懂,但这样会让原本的空白符号失去意义,这是可以使用\s来表示空白
o:只编译一次正则表达式
n:非捕获模式
p:保存匹配的字符串到${^PREMATCH}、${^MATCH}、${^POSTMATCH}中,它们在结果上对应$`、$&和$',但性能上要更好
a和u和l:分别表示用ASCII、Unicode和Locale的方式来解释正则表达式,一般不用考虑这几个修饰符
d:使用unicode或原生字符集,就像5.12和之前那样,也不用考虑这个修饰符
这些修饰符可以连用,连用时顺序可随意。例如下面两行是等价的行为:全局忽略大小写的匹配行为。
m/REG/ig
m/REG/gi
上面的修饰符,本节介绍igcmsxpo这几个修饰符,n修饰符在后面分组捕获的地方解释,auld修饰符和字符集相关,不打算解释。
i修饰符:忽略大小写
该修饰符使得正则匹配的时候,忽略大小写。
$name="aAbBcC";
if($name =~ m/ab/i){
print "pre match: $` \n"; # 输出a
print "match: $& \n"; # 输出Ab
print "post match: $' \n"; # 输出BcC
}
g和c修饰符以及\G
g修饰符(global)使得正则匹配的时候,对字符串做全局匹配,也就是说,即使前面匹配成功了,还会继续向后匹配,看是否还能匹配成功。
例如,字符串"abcabc",正则表达式"ab",在默认情况下(不是全局匹配)该正则在匹配到第一个ab后就结束了,如果使用了g修饰符,匹配完第一个ab,还会继续向后匹配,而且正好还能匹配到第二个ab,所以最终有两个ab被匹配成功。
要验证多次匹配,需要使用循环遍历的方式,而不能用if语句:
$name="aAbBcCaBc";
while($name =~ m/ab/gi){
print "pre match: $` \n";
print "match: $& \n";
print "post match: $' \n";
}
执行它,将输出如下内容:
pre match: a
match: Ab
post match: BcCabd
pre match: aAbBcC
match: ab
post match: d
以下内容,如果仅仅只是为了学perl正则,那么可以跳过,因为很难,如果是学perl语言,那么可以继续看下去。
实际上,在开启了g全局匹配后,perl每次在成功匹配的时候都会记下匹配的字符位移,以便在下次匹配该内容时候,可以从指定位移处继续向后匹配。每次匹配成功后的位移值(pos的位移从0开始算,0位移代表的是第一个字符左边的位置),都可以通过pos()函数获取。如果本次匹配导致位移指针重置,pos将返回undef。
$name="123ab456";
$name =~ m/\d\d/g; # 第一次匹配,匹配成功后记下位移
print "matched string: $&, position: ",pos $name,"\n";
$name =~ m/\d\d/g; # 第二次匹配,匹配成功后记下位移
print "matched string: $&, position: ",pos $name,"\n";
执行它,将输出如下内容:
matched string: 12, position: 2
matched string: 45, position: 7
由于匹配失败的时候,正则匹配操作会返回假,所以可以作为if或while等的条件语句。例如,改为while循环多次匹配:
$name="123ab456";
while($name =~ m/\d\d/g){
print "matched string: $&, position: ",pos $name,"\n";
}
默认全局匹配情况下,当本次匹配失败,位移指针将重置到起始位置0处,也就是说,下次匹配将从头开始匹配。例如:
$txt="1234a56";
$txt =~ /\d\d/g; # 匹配成功:12,位移向后移两位
print "matched $&: ",pos $txt,"\n";
$txt =~ /\d\d/g; # 匹配成功:34,位移向后移两位
print "matched $&: ",pos $txt,"\n";
$txt =~ /\d\d\d/g; # 匹配失败,位移指针回到0处,pos()返回undef
print "matched $&: ",pos $txt,"\n";
$txt =~ /\d/g; # 匹配成功:1,位移向后移1位
print "matched $&: ",pos $txt,"\n";
执行上述程序,将输出:
matched 12: 2
matched 34: 4
matched 34:
matched 1: 1
如果"g"修饰符下同时使用"c"修饰符,也就是"gc",它表示全局匹配失败的时候不重置位移指针。也就是说,本次匹配失败后,位移指针会向后移一位,下次匹配将从后移的这个位置处开始匹配。当位移移到了结尾,将无法再移动,此时位移指针将一直指向最后一个位置。
$txt="1234a56";
$txt =~ /\d\d/g;
print "matched $&: ",pos $txt,"\n";
$txt =~ /\d\d/g;
print "matched $&: ",pos $txt,"\n";
$txt =~ /\d\d\d/gc; # 匹配失败,位移向后移1位,$&和pos()保留上一次匹配成功的内容
print "matched $&: ",pos $txt,"\n";
$txt =~ /\d/g; # 匹配成功:5,位移向后移1位
print "matched $&: ",pos $txt,"\n";
$txt =~ /\d/g; # 匹配成功:6,位移向后移1位
print "matched $&: ",pos $txt,"\n";
$txt =~ /\d/gc; # 匹配失败:位移无法再后移,将一直指向最后一个位置
print "matched $&: ",pos $txt,"\n";
执行上述程序,将输出:
matched 12: 2
matched 34: 4
matched 34: 4
matched 5: 6
matched 6: 7
matched 6: 7
继续上面的问题,如果第三个匹配语句不是\d\d\d,而是"\d",它匹配字母a的时候也失败,不用c修饰符的时候会重置位移吗?显然是不会。因为它会继续向后匹配。所以该\G登场了。
默认全局匹配情况下,匹配时是可以跳过匹配失败的字符继续匹配的:当某个字符匹配失败,它会后移一位继续去匹配,直到匹配成功或匹配结束。
$txt="1234ab56";
$txt =~ /\d\d/g;
print "matched $&: ",pos $txt,"\n";
$txt =~ /\d\d/g;
print "matched $&: ",pos $txt,"\n";
$txt =~ /\d/g; # 字母a匹配失败,后移一位,字母b匹配失败,后移一位,数值5匹配成功
print "matched $&: ",pos $txt,"\n";
$txt =~ /\d/g; # 数值6匹配成功
print "matched $&: ",pos $txt,"\n";
执行上述程序,将输出:
matched 12: 2
matched 34: 4
matched 5: 7
matched 6: 8
可以指定\G,使得本次匹配强制从位移处进行匹配,不允许跳过任何匹配失败的字符。
如果本次\G全局匹配成功,位移指针自然会后移
如果本次\G全局匹配失败,且没有加上c修饰符,那么位移指针将重置
如果本次\G全局匹配失败,且加上了c修饰符,那么位移指针将卡在那不动
例如:
$txt="1234ab56";
$txt =~ /\d\d/g;
print "matched $&: ",pos $txt,"\n";
$txt =~ /\d\d/g;
print "matched $&: ",pos $txt,"\n";
$txt =~ /\G\d/g; # 强制从位移4开始匹配,无法匹配字母a,但又不允许跳过
# 所以本次\G全局匹配失败,由于没有修饰符c,指针重置
print "matched $&: ",pos $txt,"\n";
$txt =~ /\G\d/g; # 指针回到0,强制从0处开始匹配,数值1能匹配成功
print "matched $&: ",pos $txt,"\n";
以下是输出内容:
matched 12: 2
matched 34: 4
matched 34:
matched 1: 1
如果将上面第三个匹配语句加上修饰符c,甚至后面的语句也都加上\G和c修饰符,那么位移指针将卡在那个位置:
$txt="1234ab56";
$txt =~ /\d\d/g;
print "matched $&: ",pos $txt,"\n";
$txt =~ /\d\d/g;
print "matched $&: ",pos $txt,"\n";
$txt =~ /\G\d/gc; # 匹配失败,指针卡在原地
print "matched $&: ",pos $txt,"\n";
$txt =~ /\G\d/gc; # 匹配失败,指针继续卡在原地
print "matched $&: ",pos $txt,"\n";
$txt =~ /\G\d/gc; # 匹配失败,指针继续卡在原地
print "matched $&: ",pos $txt,"\n";
以下是输出结果:
matched 12: 2
matched 34: 4
matched 34: 4
matched 34: 4
matched 34: 4
一般来说,全局匹配都会用循环去多次迭代,和上面一次一次列出匹配表达式不一样。所以,下面使用while循环的例子来对\G和c修饰符稍作解释,其实理解了上面的内容,在循环中使用\G和c修饰符也一样很容易理解。
$txt="1234ab56";
while($txt =~ m/\G\d\d/gc){
print "matched: $&, ",pos $txt,"\n";
}
执行结果:
matched: 12, 2
matched: 34, 4
当第三轮循环匹配到a字母的时候,由于使用了\G,导致匹配失败,结束循环。
上面使用c与否是无关紧要的,但如果这个while循环的后面后还有对$txt的匹配,那么使用c修饰符与否就有关系了。例如下面两段程序,返回结果不一样:
$txt="1234ab56";
while($txt =~ m/\G\d\d/gc){ # 使用c修饰符
print "matched: $&, ",pos $txt,"\n";
}
$txt =~ m/\G\d\d/gc;
print "matched: $&, ",pos $txt,"\n";
和
$txt="1234ab56";
while($txt =~ m/\G\d\d/g){ # 不使用c修饰符
print "matched: $&, ",pos $txt,"\n";
}
$txt =~ m/\G\d\d/gc;
print "matched: $&, ",pos $txt,"\n";
m修饰符:多行匹配模式
正则表达式一般都只用来匹配单行数据,但有时候却需要一次性匹配多行。比如匹配跨行单词、匹配跨行词组,匹配跨行的对称分隔符(如一对括号)。
使用m修饰符可以开启多行匹配模式。
例如:
$txt="ab\ncd";
$txt =~ /a.*\nc/m;
print "===match start===\n$&\n===match end===\n";
执行,将输出:
===match start===
ab
c
===match end===
关于多行匹配,需要注意的是元字符.默认情况下无法匹配换行符。可以使用[\d\D]代替点,也可以开启s修饰符使得.能匹配换行符。
例如,下面两个匹配输出的结果和上面是一致的。
$txt="ab\ncd";
$txt =~ /a.*c/ms;
print "===match start===\n$&\n===match end===\n";
$txt="ab\ncd";
$txt =~ /a[\d\D]*c/m;
print "===match start===\n$&\n===match end===\n";
s修饰符
默认情况下,.元字符是不能匹配换行符\n的,开启了s修饰符功能后,可以让.匹配换行符。正如刚才的那个例子:
$txt="ab\ncd";
$txt =~ /a.*c/m; # 匹配失败
print "===match start===\n$&\n===match end===\n";
$txt="ab\ncd";
$txt =~ /a.*c/ms; # 匹配成功
print "===match start===\n$&\n===match end===\n";
x修饰符
正则表达式最为人所抱怨的就是它的可读性极差,无论你的正则能力有多强,看着一大堆乱七八糟的符号组合在一起,都得一个符号一个符号地从左向右读。
万幸,perl正则支持表达式的分隔,甚至支持注释,只需加上x修饰符即可。这时候正则表达式中出现的所有空白符号都不会当作正则的匹配对象,而是直接被忽略。如果想要匹配空白符号,可以使用\s表示,或者将空格使用\Q...\E包围。
例如,以下4个匹配操作是完全等价的。
$ans="cat sheep tiger";
$ans =~ /(\w) *(\w) *(\w)/; # 正常情况下的匹配表达式
$ans =~ /(\w)\s* (\w)\s* (\w)/x;
$ans = ~ /
(\w)\s* # 可以加上本行注释:匹配第一个单词
(\w)\s* # 可以加上本行注释:匹配第二个单词
(\w) # 可以加上本行注释:匹配第三个单词
/x;
$ans =~ /
(\w)\Q \E # \Q \E强制将中间的空格当作字面符号被匹配
(\w)\Q \E
(\w)
/x;
对于稍微复杂一些的正则表达式,常常都会使用x修饰符来增强其可读性,最重要的是加上注释。这一点真的非常人性化。
p修饰符
前面说过,通过3个特殊变量$`、$&和$'可以保存匹配内容之前的内容,匹配内容以及匹配内容之后的内容。但是,只要使用了这3个变量中的任何一个,后面的所有分组效率都会降低。perl提供了一个p修饰符,能实现完全相同的功能:
${^PREMATCH} <=> $`
${^MATCH} <=> $&
${^POSTMATCH} <=> $'
一个例子即可描述:
$ans="cat sheep tiger";
$ans =~ /sheep/p;
print "${^PREMATCH}\n"; # 输出"cat "
print "${^MATCH}\n"; # 输出"sheep"
print "${^POSTMATCH}\n"; # 输出" tiger"
o修饰符
在较老的perl版本中,如果使用同一个正则表达式做多次匹配,正则引擎将只多次编译正则表达式。很多时候正则表达式并不会改变,比如循环匹配文件中的行,这样的多次编译导致性能下降很明显,于是可以使用o修饰符让正则引擎对同一个正则表达式不重复编译。
在perl5.6中,默认情况下对同一正则表达式只编译一次,但同样可以指定o修饰符,使得即使正则表达式变化了也不要重新编译。
一般情况下,可以无视这个修饰符。
范围模式匹配修饰符(?imsx-imsx:pattern)
前文介绍的修饰符adluoimsxpngc都是放在m//{FLAG}的flag处的,放在这个位置会对整个正则表达式产生影响,所以它的作用范围有点广。
例如m/pattern1 pattern2/i的i修饰符会影响pattern1和pattern2。
perl允许我们定义只在一定范围内生效的修饰符,方式是(?imsx:pattern)或(?-imsx:pattern)或(?imsx-imsx:pattern),其中加上-表示去除这个修饰符的影响。这里只列出了imsx,因为这几个最常用,其他的修饰符也一样有效。
例如,对于待匹配字符串"Hello world gaoxiaofang",使用以下几种模式去匹配的话:
/(?i:hello) world/
表示匹配hello时,可忽略大小写,但匹配world时仍然区分大小写。所以匹配成功
/(?ims:hello.)world/
表示可以跨行匹配helloworld,也可以匹配单行的hel