大家好,又见面了,我是你们的朋友全栈君。
到目前为止,我们都是讲正则表达式的内容写在一对斜线内,如/fred/。但其实这是 m// 的简写,其中m代表match,和之前看到的 qw// 类似,我么可以自行选择用于保卫内容的一堆字符作为边界,所以上面这个例子可以改写为m{fred},m[fred],m!fred!等。
正则表达式可以在末尾添加修饰符,这些修饰符有时候也被称作标志。 表2.2 常用模式匹配修饰符
修饰符 | 规则 | 举例 | 解释 |
---|---|---|---|
i | 无关大小写匹配 | /yes/i | 可以匹配YeS |
s | 匹配任意字符 | /(.)a/s | (.)可以匹配任意字符,包括 \n (注意和字符集\s的区别) |
x | 插入辅助空白字符 | / -? [0-9]+/x | 可以忽略模式中的空格,如果希望匹配空格可以使用反斜线转义 |
si | 联合使用修饰符 | /(.)a/ | (.)可以匹配任意字符,同时a字符匹配时忽略大小写(其他组合一是允许的) |
a | ASCII解释方式 | /\w+/a | 包括A-Z a-z 0-9 _ 字符 |
u | Unicode解释方式 | /\w+/u | Unicode中定义为单词的字符 |
l | 类似于ASCII | /\w+/l | 包含ASCII方式,但单词字符的定义取决于本地设定 |
n | 非捕获分组 | /(a)(.*)(b)/n | 所有捕获变量都是未定义,$1的值为undef |
p | 自动捕获变量修饰 | /adc(.)/p | 只在当前正则表达式中开启自动捕获变量 |
默认情况下,如果字符串的开头不匹配给定模式,就会顺移到下一个字符位置继续尝试。为了让模式只匹配固定位置上的字符我们可以设置模式锚位。 表2.3 常用模式匹配锚位
锚位 | 举例 | 说明 |
---|---|---|
\A | /\Ahttps?/ | \A匹配绝对开头,匹配失败不会顺移 |
\z | /.png\z/ | \z匹配绝对末尾,.png后必须没有任何字符,才能成功匹配 |
\Z | /.png\Z/ | \Z匹配相对末尾,除\z功能外,如果.png后包含换行符\n,也可以匹配 |
^ | /^narney/m | //m的搭配表示匹配行首,m为修饰符;单独的^字符,和\A行为相同 |
$ | /narney$/m | /$/m的搭配表示匹配行尾,m为修饰符;单独的$字符,和\z行为相同 |
\b | /\bfred\b/ | \b为单词边界锚位,可以匹配任何单词的首位,属于整词匹配 |
\B | /\bfred\B/ | \B为\b的取反,可以匹配所有\b不能匹配的位置 |
正则表达式默认的匹配目标是$_,如果要制定匹配某个变量的文本,可以使用绑定操作符(binding operator) =~ ,左侧为变量,右侧为正则表达式。
#!/usr/bin/perl
my $some_other = "I dream of betty rubble.";
if ($some_other =~ /\brub/) {
print "Aye, there is the rub.\n";
}
#虽然绑定操作符看起来像是某种赋值操作,但其实并非如此!
捕获变量(如1,2)的生命周期是指捕获变量中的值可以保存多久;捕获变量中的内容一般会保持到下次成功匹配为止,即匹配失败的手不会改动上次成功匹配的内容,而成功匹配将会刷新捕获变量中的值。
#!/usr/bin/perl
if (/(bronto)?saurus (stack|burger)/) {
print "Fred wants a $2\n";
}
#有时候尽管bronto不存在,仍然需要把$1留给它,perl只看左圆括号(决定捕获变量名称,因此我们只能使用$2来取得我们想要的结果。
if (/(?:bronto)?saurus (stack|burger)/) {
print "Fred wants a $1\n";
}
#使用(?:)关闭第一个模式分组的捕获功能,这样我们可以是使用$1来引用第二个分组中的内容;
if (/(bronto)?saurus (stack|burger)/n) {
print "Fred wants a $1\n";
}
#使用//n关闭全部正则表达式中的捕获功能,此时$1和$2的值均为undef
#!/usr/bin/perl
my $name = "fred or barney";
if (/(fred) and (barney)/) {
say "I saw $1 and $2"; #匹配失败,不打印
}
if (/(fred) (and|or) (barney)/) {
say "I saw $1 and $2"; #匹配成功,打印 I saw fred and or
}
if (/(?<name1>fred) (and|or) (?<name2>barney)/) {
say "I saw $+{name1} and $+{name2}"; #匹配成功,打印 I saw fred and barney
}
if (/(?P<name1>fred) (and|or) (?P<name2>barney)/) {
#支持python风格的写法
say "I saw $+{name1} and $+{name2}"; #匹配成功,打印 I saw fred and barney
}
my $name = "fred Flint and barney Flint";
if (/fred (?<lastname>\w+) (and|or) barney (\g{lastname})/) {
#使用\g{label}反向引用
say "I saw $+{lastname}"; #匹配成功,打印 I saw Flint
}
if (/fred (?<lastname>\w+) (and|or) barney (\k<lastname>)/) {
#使用\k<label>反向引用
say "I saw $+{lastname}"; #匹配成功,打印 I saw Flint
}
表2.5 自动捕获变量及说明
自动捕获变量 | 使用//p修饰符 | 说明 |
---|---|---|
$` | ${^PREMATCH} | 匹配区段之前的内容存储 |
$& | ${^MATCH} | 匹配区段的内容存储 |
$’ | ${^POSTMATCH} | 匹配区段之后的内容存储 |
#!/usr/bin/perl
if ("Hello there, neighbor" =~ /\s(\w+),/) {
#使用自动捕获变量
print "That was ($`)($&)($').\n"; #打印: That was (Hello)( there,)( neighbor).
}
if ("Hello there, neighbor" =~ /\s(\w+),/p) {
#使用修饰符/p提升程序速度
print "That was (${^PREMATCH})(${MATCH})(${^POSTMATCH}).\n"; #打印: That was (Hello)( there,)( neighbor).
}
正则表达式的优先级只有5个级别,见表2.6: 表2.6 正则表达式的优先级(上面优先级高)
正则表达式特性 | 示例 |
---|---|
圆括号 | (…) , (?:…), (?<label>…) |
量词 | a*, a+, a?, a{n,m} |
锚位和字符序列 | abc, ^, $, \A, \z, \Z |
择一选择 | a|b, a|b|c |
原子 | a, [abc], \d, \1, \g{2} |
在编写perl程序的时候,每个程序员都避免不了要使用正则表达式,但有时候很难轻易看出一个模式能够做什么,下面这个程序非常实用,可以用于检测某些字符串是否能够被指定模式匹配以及在什么为止匹配,在将正则表达式写入主程序之前,不妨先用以下程序测试一番,检验是否复合预期要求;
#!/usr/bin/perl
#可以用以下程序调试正则表达式,验证是否符合我们期望的匹配结果
while (<>) {
chomp;
if(/YOUR_PATTERN_GOES_HERE/) {
say "Matched: |$`<$&>$'|"; #打印:Matched: |before<match>fafter|
} else {
say "No match: |$_|"; #打印:No match: |beforematchafter|
}
}
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/143987.html原文链接:https://javaforall.cn