Perl 中的正则表达式 基础

本文深入解析Perl正则表达式的各种元素,包括元字符、组单元、字符组、匹配选项等,并通过实例演示如何使用这些特性进行高效匹配。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Perl Regular expressions

Start with a simple example:
    $_ = "yabba dabba doo";
    if (/abba/) {
      print "It matched!/n";
    }
/abba/是一个正则表达式,在程序中匹配$_变量的字符串,返回值只可能是true或false
大部分/转义字符都有效
例如/first/tsecond/匹配first后跟一个Tab后跟一个second

元字符
. 匹配除换行符/n之外的任意单个字符或单元
* 匹配0个或多个在它之前的单个字符或单元, 组合.*可以匹配除换行外的任何模式
+ 匹配一个或多个在它之前的单个字符或单元
? 匹配0个或一个在它之前的单个字符或单元

在表达式中使用组单元
(fred)+ 匹配fredfred, 不匹配freddddd
fred+  匹配freddddd, 不匹配fredfred

| vertical bar 或操作符
分隔的正则表达式任意一个为真,整体均为真
/fred( |/t)+barney/
fred和barney中间有至少一个或任意多个空格和Tab的组合都能够匹配
如果要求fred和barney中间所有的分隔符都是一类则应使用
/fred( +|/t+)barney/
注意括号的使用

character classes字符组
[]用方括号表示
例如[adf2310]能匹配到括号内任何一个字符
连字符的使用,在方括号内的连字符需要/-escape掉
[a-zA-Z]任意大小写英文字母
[/000-/177]任意ASCII码(七位有效的ASCII码,非扩展)


^非操作符在字符组中使用
例如[^def]匹配任何除了d e 和f以外的任意单个字符
[^n/-z] 匹配除了n z 和-以外的任意单个字符

字符组缩略
/d [0-9]  任意数字
/w [a-zA-Z0-9] 任意数字或大小写字符
/s [/f/t/n/r] 任意空白字符,包括换行  /s*匹配没有空格或任意多空格
"非"字符组缩略
/D ^/d
/W ^/w
/S ^/s

例子:
    匹配一个或多个16进制数字/[/dA-Fa-f]+/
    [/d/D]匹配任何模式,注意.*匹配不到/n, 而[/d/D]可以

在Perl中如果使用//默认是用正则表达式进行匹配
使用m//明确说明是匹配match操作时,可以象qw//操作符一样选择你自己方便的表达式边界符如
m(fred), m<fred>, m{fred}, m[fred], m!fred!,
只要不引起歧义
由于<>在metacharacters中,如 m{(/d+)/s*>=?/s*(/d+)}
这个表达式如果用<>定界会造成歧义,因此<>最好避免使用


flags匹配选项
/i选项 忽略大小写的匹配
/yes/i

/s选项,这个选项使得.能够匹配新行符/n
/Barney.*Fred/s
允许匹配到Barney和Fred不在同一行的情况

/x选项 允许在正则表达式中使用空格甚至换行,以增强可读性
    /-?/d+/.?/d*/         #
    / -? /d+ /.? /d* /x   #增加了空格的等价写法
同样的正则表达式,加上了注释
   /
      -?      # an optional minus sign
      /d+     # one or more digits before the decimal point
      /.?     # an optional decimal point
      /d*     # some optional digits after the decimal point
    /x        # end of pattern

这些flag可以被用到同一个表达式中,例子
    if (m{
      barney # the little guy
      .*     # anything in between
      fred   # the loud guy
    }six) {  # all three of /s and /i and /x
      print "That string mentions Fred after Barney!/n";
    }


Anchors锚点
^锚点用于匹配一个字串的开始
$锚点用于匹配一个字串的结束
/^begin/ 只匹配以begin开头的字符串
/end$/   只匹配以end为结尾的字符串

注意/^this$/ 能够匹配"this"或"this/n" 结尾的换行符是不被记入的

有用的例子:
/^/s*$/ 匹配一个空行

word anchors
/b  在词的边界上(开始或结尾) 在perl中使用/b时,/b在开头则匹配开头/b在末尾则匹配末尾,其他的正则表达式实现可能定义了专门的锚点用

于区分词的开头或结尾
当/b被使用时,它所指的"词"是在//w+/组成的词(任意数字或大小写字母)
例如:
//bhunt/能够匹配hunt hunting, 不匹配shunt
/stone/b/匹配sandstone, 不匹配capstones

与之相对的/B锚点定义不在词的某个边界上
如:
//bsearch/B/ 匹配以searching开头,而且不以search结尾的单词
匹配 searches,searching
不匹配 search, researching, searchsearch

在perl中,如果没有特别指定,正则表达式匹配变量$_
使用=~操作符匹配我们指定的字符串
=~表达式返回一个布尔值说明匹配与否

    print "Do you like Perl? ";
    my $likes_perl = (<STDIN> =~ //byes/b/i);
    ...  # Time passes...
    if ($likes_perl) {
      print "You said earlier that you like Perl, so.../n";
      ...
    }

将变量作为正则表达式
    my $what = shift @ARGV;
    while (<>) {
      if (/^($what)/) {  # pattern is anchored at beginning of string
        print "We saw $what in beginning of $_";
      }
      else {
 print "We didn't see $what in beginning of $_";
      }
    }
把perl程序收到的参数作为正则表达式匹配之后的输入.
注意在perl中if...else...作用的程序块{}花括号是必须的而不是可选的!


()触发regular expression engine's Memory
可以通过括号取出待匹配字符串的一部分,当存在多个括号时,可以使用
$1 $2 等方式获得匹配到的子字符串
    $_ = "Hello there, neighbor";
    if (//s(/w+),/) {             # 匹配在空格和逗号之间的字符串
      print "the word was $1/n";  # 打印出 there
    }
使用多个记忆
    $_ = "Hello there, neighbor";
    if (/(/S+) (/S+), (/S+)/) {  #(/S+)匹配一个或多个非空格字符
      print "words were $1 $2 $3/n";
    }
如果没有可匹配的字符串模式,则变量$1为Undef


Memory persistence
如果出现了一次正确的匹配,之前所有的Memory都会被重置
所以如果使用记忆的变量,必须检查是否所有的匹配都成功了,否则,memory中保存的字符串很可能是某些之前匹配模式的内容

例子:
     $_ = "Hello there, neighbor";
    if (//s(/w+),/) {             # memorize the word between space and comma
      print "the word was $1/n";  # 打印出 there
    }

    $wilma ="()())()(/n";
    $wilma =~ /(/w+)/;  # 实际上这个匹配会失败...
    print "Wilma's word was $1... or was it?/n";
这个程序打印的结果是Wilma's word was there... or was it?
这里$1打印的结果是上一次匹配得到的值..
一种处理方法是:
    if ($wilma =~ /(/w+)/) {
      print "Wilma's word was $1./n";
    } else {
      print "Wilma doesn't have a word./n";
    }
if和while可以区分当匹配成功和不成功的情况


自动匹配变量
Perl在不使用()括号的情况下提供了三个自动匹配变量
$& 成功匹配的字符串
    if ("Hello there, neighbor" =~ //s(/w+),/) {
      print "That actually matched '$&'./n";
    }
打印结果为:That actually matched ' there,'.
注意$1仅保存there也就是(/w+)的部分,但是$&保存的字符串是整个正则表达式匹配的模式,包括前面的空格以及后面的逗号

匹配字段前的全部字符串被保存在$` 撇号
匹配字段后的全部字符串被保存在$' 单引号

使用这三个自动匹配变量的代价是有可能使得正则表达式效率少许降低.
如果效率问题很重要,又希望使用$&,可以用括号把整个pattern扩起来,然后使用$1代替$&

量化匹配
使用*,+,?不能满足需要的时候,可以用{ }花括号加上数字指定重复的次数
如/a{5,15}/ 匹配a字符出现5次到15次的情况
/(fred){3,}/ 匹配fred字符串出现三次及三次以上
//w{8}/ 匹配连续出现的8个字符,也可能是长字符串的一部分

正则表达式优先级
1. ( )圆括号 最优先
2. Quantifiers 如 * + ? 和{5,15} {6,} {9}等
3. Anchors锚点修饰符如 ^开头 结尾$ /b词边界 /B非词边界
4. 或操作符| 注意它的级别非常低 /fred|barney/ 指的是fred或barney, 而不是d或b!!

一个例子,读取输入并判断是否与指定的正则表达式匹配
    #!/usr/bin/perl
    while (<>) {                   # take one input line at a time
      chomp;
      if (/YOUR_PATTERN_GOES_HERE/) {
        print "Matched: |$`<$&>$'|/n";  # the special match vars
      } else {
        print "No match: |$_|/n";
      }
    }
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值