设为首页 收藏本站
查看: 1880|回复: 0

[经验分享] Regex in Perl

[复制链接]

尚未签到

发表于 2015-12-25 15:12:24 | 显示全部楼层 |阅读模式
  
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 $& ;
DSC0000.jpg
  解释:
第一阶段
  首先在 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

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-156279-1-1.html 上篇帖子: Perl中的特殊符号 下篇帖子: Perl篇:获取操作系统的信息
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表