perlre——参考Perl正则表达式
本页面描述了Perl的正则表达式语法。如何描述使用正则表达式匹配操作,加上各种相同的例子,看看m / g /ydF4y2Ba
和/ / /
在perlop。
匹配的操作可以有各种各样的修饰符。的修饰词与正则表达式的解释在下面列出。的修饰符改变操作的行为,明白了perlop /“/ /”和perlop / ' ' s / /”。
如果使用场所
实际上,地图是取自当前语言环境。看到perllocale。
这些通常是写成“/ x
修饰符”,即使在问题可能不是一个斜杠分隔符。事实上,这些修饰符也可以嵌入到正则表达式本身使用新的(?…)
构造。见下文。
的/ x
修饰符本身需要更多的解释。它讲述了正则表达式解析器忽略空格内斜和字符类。您可以使用它来打破你的正则表达式(稍微)部分更具可读性。的#
性格也被视为元字符介绍评论,就像在普通的Perl代码。这也意味着,如果你想要真正的空白或#
模式中的角色,你将不得不逃离他们或编码使用八进制或十六进制转义。综上所述,这些特征很长的一段路要走使Perl的正则表达式更具可读性。看到C评论删除代码perlop。
用于模式匹配的正则表达式的模式提供诸如Version 8 regexp的例程。(事实上,例程(冷淡地)来自亨利·斯宾塞的自由可再发行的重新实现的V8的例程)。看到Version 8正则表达式获取详细信息。
特别是以下元字符有自己的标准egrep有点儿…的含义:
\ "下一个字符^匹配的开始。匹配任何字符(除换行符)$匹配线的结束(或在换行符结束之前)|()交替分组[]字符类
默认情况下,“^”角色是保证只匹配字符串的开始,“$”字符只结束(或换行符前最后)和Perl与假设某些优化字符串只包含一行。嵌入式换行不匹配“^”或“$”。然而,您可能希望将作为一个多行字符串缓冲区,这样“^”将匹配字符串中的任何换行符之后,“美元”将匹配任何换行符之前。在更多的成本开销,这可以通过使用模式匹配操作符/ m修饰符。(老程序通过设置$ *
,但这种做法现在已经弃用。)
促进多行替换,' '。“性格不匹配换行符,除非你使用/秒
修饰符,实际上告诉Perl假装字符串是一行,即使它不是。的/秒
修饰符也覆盖的设置$ *
,以防你有一些(严重违纪)老代码,使它在另一个模块。
以下标准量词是公认的:
*匹配0次或更多+匹配1次或更多?匹配1或0 * {n}完全匹配n * {n}匹配至少n次{n, m}匹配至少n以上m乘以
(如果一个花括号发生在其他任何情况下,它被当作一个普通字符)。“*”修饰符是等价的{0}
,“+”修饰符{1,}
,' ' ?“修改器{0,1}
。n和m有限积分值小于65536。
默认情况下,量化子模式是“贪婪的”,也就是说,它将匹配尽可能多地(给定一个特定的开始位置),同时仍然允许其余的模式匹配。如果你想匹配的最小次数可能,按照量词“?”。注意,含义不改变,只是“贪吃”:
* ?匹配0或多个* + ?匹配1次以上? ?{n}匹配0或1时间?完全匹配n次{n} ?匹配至少n乘以m} {n, ?匹配至少n以上m乘以
因为模式是处理双引号字符串,以下工作:
选项卡\ t选项卡(HT) \ n换行符(低频,NL) \ r返回(CR)提要(FF) \ \ f形式报警(贝尔)(贝尔)\ e逃脱(想想troff) (ESC) \ 033八进制char(认为)时)\ x1B十六进制字符c \[控制字符\ l小写的下一个字符(vi) \ u大写的下一个字符(vi) \ l小写直到\ e (vi)直到\ \ u大写e (vi) \ e结束案例修改(vi) \问报价regexp元字符直到\ e
如果使用场所
实际上,使用的地图吗l \
,L \
,\ u
和< \ U >是取自当前语言环境。看到perllocale。
此外,Perl定义如下:
\ w匹配一个“单词”字符(字母数字+“_”)\ w匹配一个单词字符\ s匹配一个空格字符\ s匹配一个非空字符\ d匹配一个数字字符\ d non-digit字符相匹配
请注意,\ w
匹配一个字母数字字符,而不是一个整体。匹配一个单词你需要说\ w +
。如果使用场所
在起作用时,产生的字母字符的列表吗\ w
从当前的语言环境。看到perllocale。你可以用\ w
,\ W
,\ s
,\ S
,\ d
,\ D
在字符类(尽管不是作为一个范围的两端)。
Perl定义以下零宽度断言:
\ b \ b匹配一个单词边界匹配非(字边界)\只匹配字符串的开始\ Z年底只匹配字符串(或在换行符结束之前)\ G匹配只有在先前的m / G /离开(只能用/ G)
一个单词边界(\ b
)被定义为有两个字符之间\ w
一边的\ W
另一方面(秩序),计算虚拟人物的开始和结束字符串匹配\ W
。(在字符类\ b
代表了退格而非单词边界。)的、一个
和\ Z
就像“^”和“$”,只是他们不会匹配时多次吗/ m
修饰符使用,而“^”和“$”将匹配在每一个内部边界线。以匹配实际的字符串,而不是忽视换行符,您可以使用\ Z (? ! \ n)
。的\ G
断言可以用于全球匹配(使用链m / g /
),如中描述perlop /“Regexp说运营商”。
写作时也很有用lex
例如扫描仪,当你有几个regexp要匹配的子字符串的字符串,看到前面的参考。实际的位置\ G
将匹配也可以影响使用吗pos ()
作为一个左值。看到perlfunc / pos。
当托架结构(…)
,\ <数字>第位子字符串匹配。以外的模式中,总是使用“$”而不是“\”前的数字。(虽然\ <数字>符号可以在罕见的场合工作电流模式外,不应依赖。见下面的警告。)<数字>(和美元的范围美元的
,$ &
,美元的
)延伸到封闭块或eval结束的字符串,或到下一个成功的模式匹配,以先到期者作准。如果你想使用括号分隔子模式(例如,一组备选方案)不保存子模式,遵循(?:。
你可以尽可能多的括号。如果你有超过9子字符串,变量$ 10,11美元,……参考相应的子字符串。模式中,\ \ 11等参考子如果有至少许多backreference前左括号。否则(向后兼容性)是一样的\ \ 010,退格,011年\ \ 11一样,一个选项卡。等等。(通过\ \ 1 9总是反向引用。)
$ +
返回最后一个括号匹配匹配。$ &
返回匹配整个字符串。(0美元
用于返回相同的东西,但不是任何更多。)美元的
之前返回所有匹配的字符串。美元的
后返回所有匹配的字符串。例子:
s / ^ ([^] *) * ([^] *) / $ 2 $ 1 /;#交换前两个字
如果(/时间(. .):(. .):(. .)/){小时= 1美元;分钟= 2美元;秒= 3美元;}
一旦perl看到你需要之一$ &
,美元的
或美元的
在程序的任何地方,它必须提供每一个模式匹配。这可以使你的程序慢下来。相同的机制来处理这些提供了使用$ 1,$ 2,等等,所以你支付相同的价格,为每一个正则表达式包含捕获括号。但是如果你从来没有使用$ &,等等,在您的脚本,然后regexp没有捕捉括号不会受到处罚。所以避免&、美元的美元,美元的如果可以,但如果你不能(和一些算法真的很感激),一旦你使用一次,使用它们,因为你已经付出了代价。
你会注意所有斜在Perl中元字符是字母数字,等\ b
,\ w
,\ n
。不像其他正则表达式语言,没有斜符号不是字母数字。所以任何看起来像\ \ \(\)\ \ >,< \{或\}总是解释为一个文字字符,而不是一个元字符。这使它简单的引用一个字符串,你想要使用的模式,但你害怕可能包含元字符。报价只是所有非字母数字字符:
$ = ~ s /模式(\ W) / \ \ 1美元/ g;
您还可以使用内置命令quotemeta ()
函数来做到这一点。一个更简单的办法引用元字符的匹配操作符
/非上市\问引用美元\ E非上市/美元
Perl扩展正则表达式的语法定义了一个一致的。语法是一对括号与一个问号在括号内的第一件事(这是一个旧版本的Perl语法错误)。问号后面的字符的功能扩展。几个扩展已经支持:
/ x
开关是用来使空白格式,简单#
就足够了。分割(/ \ b (?: | | b c) \ b /)
就像
分割(/ \ b (a | | c) \ b /)
但不吐出额外的字段。
/ \ w + (? = \ t) /
匹配一个单词后跟一个选项卡,而不包括选项卡$ &
。/酒吧/ foo (? !)
匹配任何发生的“foo”不是“酒吧”紧随其后。但是要注意,超前和向后插入并不是一样的。你不能使用这个向后插入:/ / (? ! foo)酒吧
不会找到一个发生的“酒吧”,之前是不“foo”。这是因为foo (? !)
只是说接下来不能“foo”——这不是,这是一个“酒吧”,所以“foobar”比赛。你必须做点什么/ / (? ! foo)…酒吧
的。我们说“喜欢”,因为你的“酒吧”的情况下没有前三个字符。你可以覆盖:/ (?:foo(? !)……| ^ . . ?)酒吧/
。有时还容易只是说:如果(/ foo / & & $ = ~ /酒吧/美元)
(我)?
前面的模式。例如:美元模式=“foobar”;如果(美元/模式/ i)
#更灵活:
美元模式= "(?我)foobar”;如果(/模式/美元)
具体选择的问号和新的最小匹配构造是因为1)问号在年长的正则表达式是很罕见,和2)每当你看到一个,你应该停下来,“问题”到底是什么。这是心理学……
正则表达式匹配涉及概念的一个基本特征回溯。(需要时)使用的正则表达式量词,即*
,* ?
,+
,+ ?
,{n, m}
,{n, m} ?
。
对于一个正则表达式来匹配,整个正则表达式必须匹配,而不只是它的一部分。如果模式含有一个量词的开始成功的方式导致模式失败,后面部分匹配引擎支持和重新计算开始的部分,这就是为什么它被称为回溯。
回溯的下面是一个示例:假设您想找到这个词后“foo”字符串中的“食物是foo桌上。”:
$ _ =“食物是foo桌上。”;如果(/ \ b (foo) \ s + (\ w +) / i){打印“2美元1美元。\ n”;}
当匹配运行时,正则表达式(第一部分\ b (foo)
)发现了一个可能的匹配字符串的开始,并加载与“Foo”1美元。然而,一旦匹配引擎看到“Foo”后没有空格,保存在1美元,它意识到错误并开始一遍又一遍的一个字符后,初步匹配。这一次它直到下一个发生“foo”。完整的正则表达式匹配这一次,得到的预期输出表遵循“foo”。
有时候最小匹配可以帮助很多。想象你想匹配之间的一切“foo”和“棒”。最初,你写的是这样的:
$ _ = "栏下的食物是在谷仓。”;如果(/ foo (. *) bar){打印”< $ 1 > \ n”;}
也许意外收益:
了> < d是在酒吧里
这是因为。*
你是贪婪的,所以之间的一切吗第一个“foo”和去年“酒吧”。在这种情况下,更有效的使用最小匹配,以确保你得到文本之间的“foo”,第一个“酒吧”。
如果(/ foo(. * ?)酒吧/){打印“< $ 1 > \ n”}了< d下>
这是另一个例子:假设你想匹配一个数字的字符串,你也想让前面的比赛的一部分。你写这个:
$ _ =“我有两个数字:53147”;如果(/ (. *)(\ d *) /){#错了!打印”开始是< > 1美元,号码是< > 2美元。\ n”;}
不会工作,因为。*
是贪婪,吞并整个字符串。作为\ d *
可以在一个空字符串匹配完整的正则表达式匹配成功。
开始是<我有两个数字:53147 >、< >。
这里有一些变种,其中大部分不工作:
$ _ =“我有两个数字:53147”;@pats = qw {(. *) (\ d *), (. *) (\ d +) (. * ?) (\ d *) (. * ?) (\ d +) (. *) (\ d +) $ (. * ?) (\ d +) $ (. *) \ b (\ d +) $ (. * \ d) (\ d +) $};
美元的帕特(@pats) {printf“% -12年代”,帕特美元;如果(pat /) / ${打印”< $ 1 > < 2美元> \ n”;其他}{打印“失败\ n”;}}
这将打印出:
(. *)(\ d *) <我有两个数字:53147 > < > (. *)(\ d +) <我有两个数字:5314 > < 7 > (. * ?)(\ d *) < > < > (. * ?) (\ d +) <我> < 2 > (. *)(\ d +) $ <我有两个数字:5314 > < 7 > (. * ?)(\ d +) $ <我有两个数字:> < 53147 > (. *)\ b (\ d +) $ <我有两个数字:> < 53147 > (. * \ d) (\ d +) $ <我有两个数字:> < 53147 >
如你所见,这可能有点棘手。重要的是要意识到一个正则表达式只是一组断言,给成功的定义。可能有0、1或几种不同的方式对特定字符串的定义可能会成功。如果有多种方法可以成功,你需要了解回溯知道各种各样的成功实现。
当使用断言和否定,这都可以变得更欺骗者。想象你想找到一个序列non-digits紧随其后的是“123年”。你可能会试图把它写成
$ _ =“ABC123”;如果(/ ^ \ D *(? ! 123) /){#错了!打印”是的,没有123年的$ _ \ n”;}
但不会匹配;至少,不是你希望的方式。它声称,没有123年的字符串。这里有一个清晰的模式匹配,为什么与流行的期望:
$ x =“ABC123”;$ y = ' ABC445 ';
打印“1:有1美元\ n”如果$ x = ~ / ^ (ABC) (? ! 123) /;打印“2:有1美元\ n”如果$ y = ~ / ^ (ABC) (? ! 123) /;
打印“3:有1美元\ n”如果$ x = ~ / ^ (\ D *) (? ! 123) /;打印“4:有1美元\ n”如果$ y = ~ / ^ (\ D *) (? ! 123) /;
这个打印
2:有ABC 3:有AB 4:美国广播公司(ABC)
你可能预期测试3失败,因为它似乎更通用的版本测试1。它们之间的重要区别是,测试3包含一个量词(\ D *
),所以可以使用回溯,而测试1不会。发生了什么是,你问“真的在x美元,0或多个non-digits后,你有不是123吗?“如果模式匹配器让\ D *
扩展到“ABC”,这将导致整个模式失败。搜索引擎最初将匹配\ D *
“ABC”。然后它将尝试匹配(123年? !
当然,与“123”失败。但是因为一个量词(\ D *
)中使用正则表达式,搜索引擎可以回溯并重试匹配不同的匹配完整的正则表达式。
现在,这种模式真的想要成功,所以regexp回退并重试,让它使用标准\ D *
扩大“AB”这一次。现在确实有一些后“AB”不是“123”。事实上“C123”,这就足够了。
我们可以通过使用这两种处理这个断言和否定。我们将在1美元说第一部分必须后跟一个数字,实际上,它还必须紧随其后的东西不是“123”。记住,超前任意表达式——他们只看,但不消耗任何字符串的匹配。所以重写这个方法产生你所期望的;例5将会失败,但案例6成功:
打印“5:有1美元\ n”如果$ x = ~ / ^ (\ D *) (? = \ D) (? ! 123) /;打印“6:有1美元\ n”如果$ y = ~ / ^ (\ D *) (? = \ D) (? ! 123) /;
6:有美国广播公司
换句话说,两个零宽度断言相邻像他们的值在一起工作,就像你会使用任何装入的断言:/ ^ $ /
匹配只有在你在一行的开始和结束的同时行。更深层次的基本事实是,并列在正则表达式总是意味着,除了当你写一个显式的或使用竖线。/ ab /
意味着匹配“比赛”,(然后)“b”,尽管尝试匹配在不同位置,因为““不是零宽度断言,但one-width断言。
一个警告:特别复杂的正则表达式可以指数时间才能解决由于巨大数量的可能方式他们可以使用回溯尝试匹配。例如这将花很长时间运行
/ (({0,5}){0,5}){0,5}/
如果你使用*
的而不是限制为0到5匹配,那么它将永远,或直到你跑出栈空间。
如果你不熟悉的“常规”Version 8 regexp例程,这是模式匹配规则不是上面所描述的。
任何单个字符匹配本身,除非它是一个元字符这里描述的特殊意义或以上。你会导致角色通常是按字面意思理解的函数作为元字符加上前缀“\”(例如,“\。“匹配”。”,而不是任何字符;“\ \”匹配“\”)。一系列的字符匹配的字符在目标字符串,所以模式blurfl
将匹配“blurfl”在目标字符串。
您可以指定一个字符类,通过封闭字符的列表[]
之一,它将匹配任何字符列表中。如果第一个字符后,“[”是“^”,类不匹配任何字符列表中。在一个列表,“-”字符用于指定一个范围,所以无所不包的
代表所有的人物之间的“一个”和“z”,包容性。
字符可能被指定使用元字符的语法类似使用C:“\ n”匹配换行符,“\ t”选项卡,“\ r”回车,“\ f”一种饲料,等更广泛,\nnn,在那里nnn是一个八进制数字的字符串匹配字符的ASCII值是什么nnn。同样,x \神经网络,在那里神经网络十六进制数字,字符的ASCII值匹配的吗神经网络。表达式\ cxASCII字符匹配的控制x。最后,' '。”除了“\ n”字符匹配任何字符(除非你使用/秒
)。
您可以指定一系列的替代模式使用“|”分开,这样费| 5 |敌人
将匹配任何“费用”,“5”或“敌人”在目标字符串(会吗f (e | | o) e
)。注意,第一个替代包括从过去的模式分隔符(“(”,“[”,或模式)的开头第一个“|”,最后选择包含从最后一个分隔符“|”到下一个模式。出于这个原因,它是常见的做法包括选择括号内,以减少混淆他们开始和结束的地方。但是要注意,“|”被解释为方括号的文字,如果你写(费用| 5 |敌人)
你真的只匹配[feio |)
。
在一个模式中,您可以指定子模式供以后参考通过将它们包含在圆括号中,你可以参考nth子模式使用元字符\后面的模式n。子模式的基础上,从左到右编号顺序的开括号。注意,backreference匹配任何实际上的子模式匹配字符串被检查,不是子模式的规则。因此,(0 | 0 x) \ d * \ \ 1 \ d *
将匹配“0 x1234 0 x4321”,而不是“0 x1234 01234”,因为子模式1实际上与“0 x”,尽管规则0 | 0 x
可能匹配0领先第二号码。
有些人太用于写作之类的东西
$ = ~ s /模式(\ W) / \ \ \ 1 / g;
这是祖父级的皇家园艺的替代品以避免震惊了sed成瘾者,但这是一个肮脏的习惯。这是因为在PerlThink,右手边的/ / /
是一个双引号字符串。\ 1
在通常的双引号字符串意味着k。传统的Unix的意义\ 1
是凑合的/ / /
。然而,如果你养成这样的习惯,你给自己带来麻烦,如果你再添加一个/ e
修饰符。
s / (\ d +) / \ 1 + 1 /如;
或者如果你想做的事
s / 1000 (\ d +) / \ /;
你不能说消除歧义000年\ {1}
,而你可以修复它{1}000美元
。基本上,插值的操作不应混淆backreference匹配的操作。当然他们的意思是两个不同的东西左一边的/ / /
。
“掌握正则表达式”perlbook由Jeffrey fiedl的用于检查电子邮件地址)。