regex literal
代表正则文字, 就是 m/regex / 部分中的 regex, 这部分有自己的解析规则. 用 Perl 的行话就是 "表示正则含义的双引号字符串(regx-aware double-quoted string)", 及处理后传递给正则引擎的结果.
正则文字支持的特性 :
1. 变量插值. 如 m/$str/, 其中的 $str 会被扩展成变量内容, 但 $str 内部的变量不会被展开. 但不支持散列内插. (Perl 本身就不支持散列内插).
2. 大小写转换. 如 m/\l $str/ 或 m/\U $str\E / 等. 其等价函数是 \l => lcfirst(), \u => ucfirst(), \L .. \E => lc(), \U .. \E => uc().
3. 文字文本. 如 m/\Q $str\E /. 其等价函数是 qutoemeta()
3.1 希望匹配的是此模式内所包含的变量所代表的字符, 而不是该变量中的正则表达式.
3.2 对于不能识别的转义字符, \Q .. \E 将会导致警告 "unrecognized escape". 4. 命名的 Unicode 字符
其他
在 match 操作中, 当分隔符是 '/' 或 '?' 时, 可省略 m/regex/ 中的 m.
不能对本作用域的局部变量调用 local, 但是可以对其更外层作用域的局部变量调用 local.
local 是行为, 而 my 既是行为也是声明.
与正则相关的特殊变量
Symbol
Effect
Default
$'
匹配之前的文本
$&
匹配的文本
等价于 substr($text, $-[0], $+[0] - $-[0])
$`
匹配之后的文本
$1
第一组匹配文本
$2
第二组匹配文本
$^N
括号最后结束的一组匹配文本
$+
编号最大的一组匹配文本
$"
数组内插到标量时, 默认的分隔符
空格
@-
各个捕获的起始位置 (0 是匹配的起始)
@+
各个捕获的结束位置后的一位 (0 是匹配的结束后的一位)
(\w+) 与 (\w)+
如 "\n\n\nq1w2e3r4\t\t\t" =~ (\w+)
两者匹配的内容是相同的. 区别在于捕获括号中的内容不同. 前者将捕获整个可匹配的字串, 因此, 例子中 $1 的值是 "q1w2e3r4". 后者则会迭代捕获新的内容, 因此 $1 只保留最后一个字符 "4".
(x?) 与 (x)?
在 (x?) 中, 捕获必然发生, 但是其捕获的内容可以为空字符, 也就是 "". 但是在 (x)? 中情况则不同, 因为捕获不是必须发生, 因此 $1 的值可能会出现 def 或 x.
qr 运算符生成 regex 对象
主要用来把正则表达式封装为一个单元, 构建更强大的正则表达式, 以提高效率。
regex 对象一旦封装完成, 对应的匹配模式就不能更改了。即: 不能向已构建的正则对象添加新的模式。
my $regex = qr/$var/ # 支持普通变量内插
my $string = qr/$regex/ # 也支持嵌套的 regex 对象内插
在 scalar context 中, 正则对象被认为是一个含有模式说明符的正则表达式字符串。
match 运算符 (m/ regex /xismgc )
在 scalar context 中, =~ 返回 0 或 1. 代表不匹配和匹配。
在 list context 中, =~ 返回捕获所匹配的内容。
#!/usr/bin/perl -w
use 5.010 ;
# 拆分 IP 地址
my $ip = "192.168.1.1" ;
my ($ip1, $ip2, $ip3, $ip4) = $ip =~ m/(\d+)/g ; # list context
say $ip1 ; # 192
say $ip2 ; # 168
say $ip3 ; # 1
say $ip4 ; # 1
字符串中的 “当前位置” 属性与 /g 修饰符
每个字符串都有一个 “当前位置” 属性, 表示在正则表达式应用到这个字符串时, 驱动程序的开始锚点。可通过 pos() 设定与获得。任何创建和修改字符串的行为都会造成 “当前位置”被重置。即,“当前位置” = undef, 从而指向字符串的起始。
/g 修饰符的作用就是:
如果本次成功匹配, 则将 ”当前位置“ 设置为成功匹配结束的位置。
如果匹配失败,则将重置 “当前位置” 。即, 将 “当前位置” 设置为 undef, 此时意为传动装置将从字符串开头开始驱动。
#!/usr/bin/perl -w
use 5.010 ;
my $str = "192.168.1.1" ;
$str =~ m/\w+/g ; # 将匹配 192
my $pos = pos($str) ;
say $pos ; # 3
/gc 修饰符
/c 修饰符指: 当匹配失败后, 不修改 “当前位置” 属性。
当指定 /g 修饰符时才可指定 /c 修饰符。所以常常说 /gc。
\G 修饰符
告诉传动装置, 不要启动驱动过程, 如果在此处(即字符串的 “当前位置” 属性)无法匹配, 则宣告失败。
不能和全局性多选结构一起使用, 否则结果是未定义的。
substitution 运算符 (s/ regex/ replacement /xismge )
match 可以省略 m, 但是 substitution 不能省略 s。
substitution 无论在 scalar context 中还是 list context 中, 返回值都表示替换的次数, 或空字串。
/g 修饰符
全局替换。
/e 修饰符
replacement 在 scalar context 中重新求值。
#!/usr/bin/perl -w
use 5.010 ;
my $str = "current: time." ;
$str =~ s/time/localtime/eg ; # 对 localtime 进行求值
say $str ; # current: Thu Oct 13 10:08:31 2011.
多次使用 /e 修饰符, 表示对 replacement 进行多次求值。
#!/usr/bin/perl -w
use 5.010 ;
my $str = "Three times evaluate: var" ;
my ($var1, $var2, $var3) = ('$var2', '$var3', 3) ;
$str =~ s/var/$var1/eeeg ;
say $str ; # Three times evaluate: 3
Perl 的专有特性
动态正则结构 : (??{ perl code })
每次遇到这种结构, 就会立即执行 perl code 代码. 执行的结果将立即被作用于当前的匹配.
perl code 的返回值会被认为是正则文字的一部分.
"3xxxyy" =~ m/(\d) (??{"x{$1}"})/ ; # 可以匹配 "3xxx"
应用:
匹配任意深度的嵌套.
#!/usr/bin/perl -
use 5.010 ;
my $x = "int fun(int a, int (*pfun)(char b))" ;
my $level_n ; # 先声明, 下面才能使用
$level_n = qr/\((?>[^()]+|(??{$level_n}))*\) / ;
$x =~ m/$level_n/ ;
say $& ;
解释:
第一阶段
首先在 fun( 的开括号处遇到匹配,
接着进入固化分组, [^()]+ 匹配了 int fun(int a, int (*pfun)(char b))
第二阶段
再遇到开括号, 因为 int ( 这个开括号无法匹配 [^()]。 因此进入第一层多选结构 (??{$level_n}) 的判定。 这个分支是动态正则结构, 因此会立即进入动态结构进行匹配操作。
此时动态正则结构 (??{$level_n}) 展开为自身 “\((?>[^()]+|(??{$level_n}))*\)”, 并对 "(*pfun)(char b))" 进行匹配。
当 (*pfun 遇到 $level_n 中的 “\((?>[^()]+|(??{$level_n}))*\)” 时, 得到匹配, 因此继续向后进行匹配。
(*pfun 因 “\((?>[^()]+|(??{$level_n}))*\)” 得到匹配。
此时, 遇到 "(*pfun)" 中的 “)”. 且正则文字中的 [^()]+ 无法匹配, 并进入第二层 “(??{$level_n})” 多选分支, 但是字符 “)” 对于多选分支展开后的正则文字 “\((?>[^()]+|(??{$level_n}))*\)” 依然得不到匹配, 因此退出第二层多选分支。
驱动程序前进, “)” 遇到第一层的 “\((?>[^()]+|(??{$level_n}))*\)”, 得到匹配。 完成并退出第一层多选分支。
第三阶段
此后同理。
嵌套代码结构 : (?{ arbitrary perl code })
每次遇到此结构, 立即执行 perl 代码.
此结构较 "动态正则结构" 更为通用, 因为不需要 arbitrary perl code 的返回值作为正则文字的部分进行匹配. 在调试中十分常见.
#!/usr/bin/perl -
use 5.010 ;
my $x = "have a nice day" ;
$x =~ m{(?{print "."})day$}x ; # 应该会输出 13 个 "." 号, 但是在 windows 下使用 strawberry perl, 只输出了一个 "."
运维网声明
1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网 享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com