(八) 正则表达式——基础介绍(元字符、模式分组、单词锚位/b、模式匹配操作符(m//)与修饰符/isx、捕获变量等)

本文主要是介绍(八) 正则表达式——基础介绍(元字符、模式分组、单词锚位/b、模式匹配操作符(m//)与修饰符/isx、捕获变量等),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 一、元字符介绍与优先级
  • 二、模式分组——捕获组(反向引用)
  • 三、模式匹配操作符(m//)与修饰符(/i、/s、/x、/a、/u、/a)
  • 四、单词锚位
  • 五、绑定操作符(=~)
  • 六、模式中的内插
  • 七、格式转换问题
  • 八、捕获变量
    • 8.1、变量捕获及其存续期($1、$2 ...
    • 8.2、不捕获模式(?:
    • 8.3、命名捕获(?< Label >Pattern
    • 8.4、自动捕获变量( $&、 $'、 $`
  • 九、模式测试程序

  正则表达式是Perl内嵌的、自成一体的微型编程语言,在Perl中也叫 模式(pattern),主要用来提高 对字符串的处理能力

一、元字符介绍与优先级

  在介绍元字符之前,先了解一下正则表达式在Perl中的简单运用方式:

#格式转换:utf-8 转换成gbk格式
use encoding 'utf8', STDOUT=>'gbk';         #说明:采用的Perl版本为5.012, 支持encoding模式,如果是其它版本可能会出错$_ = "yabba dabba doo";      #被查找的特殊变量一定放在特殊变量里$_
if(/abba/){                  #界定符可以不使用双斜杠//print "配上了\n";
}
else{print "没配上\n";
}

  当模式匹配的对象是$_的内容,只需要把模式写在一对斜线(/)中就可以了,模式本身就是一串简单的字符序列。由于模式匹配通常用来返回真或者假,所以往往会用在if或者while的条件表达式里。
   模式匹配除了匹配简单的直接量字符串,还可以匹配一些特殊字符,称之为元字符,它们在正则表达式中代表着特殊含义。

  1. 普通常用元字符如下表:
普通字符含义
点号(.)匹配任意一个字符的通配符(换行符“\n”除外
反斜线\表示转义,任意元字符前加反斜线,都会失去作用成为普通字符;要匹配真正的反斜线,需用两个反斜线表示
圆括号()模式分组——对字符串进行分组,以便反向引用
|择一匹配——要么匹配左边内容,要么匹配右边内容
字符集字符集——通常写在方括号[ ]内表示,只匹配单个字符,可以是字符集中列出的任意一个
脱字符^一般在字符集开头的地方加上,表示这些字符除外
连字符-在字符集中表示始末范围;在字符集括号外无特殊意义
[^n\-z]表示匹配n,连字符与z以外的任意字符
  1. 三大数量元字符及通用量词、贪婪量词({ }):
(贪婪)数量元字符含义贪婪量词含义
星号(*)匹配符号前面的条目0~任意次*?匹配的字符串越短越好
.*匹配任意字符0~任意次(换行符除外).*?匹配的字符串越短越好
加号(+匹配符号前面的条目1~任意次+?匹配的字符串越短越好
问号(?)匹配符号前面的条目0~1次??优先考虑0次的情况
花括号({ })指定具体的重复次数范围{ }?
{n,m}匹配n ~ m个{n,m}?优先匹配n次的情况
{n}匹配 n 个
{n,}匹配 n ~ 任意个{n,}?优先匹配n次的情况
{,m}匹配 0 ~ m个{,m}?优先匹配0次的情况
$_ = "abcdddddeee";
if(/a?b*c+d{2,5}e{2,}/){   #大括号——指定通用量词print "配上了\n";
}
  1. 常用字符集简写: \w+——表示一个单词;\d+——表示一个数字
字符集简写(大写反义简写)含义
\d匹配任意一个数字,等价于字符集[0-9]
\s匹配任意一个空白符,等价于字符集[\t\n\r\f ]
\w匹配任意一个数字、字母和下划线,等价于[A-Za-z0-9_]
\D匹配非数字字符
\S匹配非空白字符
\W匹配非单词字符
  1. 正则表达式优先级顺序由高到低):
正则表达式特性示例
圆括号(分组或捕获)(…),(?: …),(?<Label>…)
量词a*,a+,a?,a{n,m}
锚位和序列abc,^,$,\A,\b,\z,\Z
择一竖线a|b|c
原子a,[abc] ,\d,\1,\g{2}
#优先级
$_ = "barney";
if(/^(fred|barney)$/){print "配上了\n";
}

二、模式分组——捕获组(反向引用)

  在正则表达式中,可以使用圆括号()对字符串进行分组,我们可以用反向引用来引用圆括号中的模式所匹配的文字,这个行为称之为捕获组。反向引用不必紧接在对应的捕获组括号后边,其写法是在反斜线后边接上数字编号,比如\1、\2这样相应的数字表示对应顺序的捕获组,只要依次点算左括号(包括嵌套括号)的序号即可。

use 5.010;        #引入新版本写法#模式分组(反向引用——相对、绝对)   
if(/(fred)+/){print "找到了\n";}else{print "没找到\n";}             #匹配fredfredfred这样的字符串
if(/(.)(..)\1\2/){print "找到了\n";}else{print "没找到\n";}         #模式分组——新写法
if(/(.)(..)\g{1}\g{2}/){print "找到了\n";}else{print "没找到\n";}   #花括号——绝对引用,新写法
if(/(.)(..)\g{-1}/){print "找到了\n";}else{print "没找到\n";}       #负号——相对引用,代表前一个括号

  从Perl 5.010版本开始,支持一种新的反向引用写法。不在只是用简单的反斜线和组号,而是\g{N} 这种形式,N是方向引用的组号这种写法的好处是,组号可以使用负数

  • 绝对反向引用一一对应):if(/(.)(…)\g{1}\g{2}/),g{1}代表第一个括号(.),g{2}代表第二个括号(…);
  • 相对反向应用就近原则):if(/(.)(…)\g{-1}/),g{-1}代表最近的一个括号(…)。

在TextPad上编码采用的是UTF-8模式,而控制端口采用的是GBK模式,为了统一编码格式不至于出现打印乱码,需在文件开头添加代码:

三、模式匹配操作符(m//)与修饰符(/i、/s、/x、/a、/u、/a)

  前述的模式写法都是采用双斜线的写法表示,事实上,这是m//(模式匹配操作符)的简写。类似qw//简写提到的,可以选择任何成对的定界符。所以,我们可以写成m(fred),m{fred},m<fred>,m^fred^等。

  说明:简写省略m,仅限于使用双斜线定界符;如果使用其它定界符,m不可省略。

  Perl中有多种模式匹配修饰符,也称标志(flag)。它们是一些追加在模式表达式末尾定界符后面的字母,用来改变默认的匹配行为。具体见下表:其中字符解释意义的修饰符是由Perl 5.014开始加入。

字符集简写(大写反义简写)含义
\i进行大小写无关的匹配
\s匹配任意字符,它会使点号(.)匹配任意字符,包括换行符
\x加入空白符允许在模式中任意添加空白符,增加易读性
\g可以执行全局匹配
\m可以执行多行匹配
\aASCII范围内进行字符解释
\uUnicode范围内进行字符解释
\locale范围内进行字符解释

说明:正则表达式/m修饰符:

  • /m修饰符规定正则表达式可以执行多行匹配
  • /m修饰符的作用是修改 ^ 和 $ 在正则表达式中的作用,让它们分别表示行首和行尾
  • 在默认状态下,一个字符串无论是否换行只有一个开始 ^ 和结尾 $,如果采用多行匹配,那么每一个行都有一个 ^ 和结尾 $
#单一选项修饰符——/x
print "请输出一个数:";
chomp($_ = <STDIN>);
if(/-?        #?_0个或1个负号\d+       #\d+_1个或多个数字,等价于[0-9]+\.?       #0个或1个小数点\d+       #1个或多个数字/x){      #\x_加入空白符,易读print "你输入的数是:$_\n";
}
else{print "你输入的不是数:$_\n";
}#组合选项修饰符——/x
$_ = "I saw Barney\ndown at the bowling alley\nwith fred\nlast night.\n";
print;
if(/barney     #找barney.*         #任意字符,包括换行符\nfred       #找fred/isx){     #/s_匹配任意字符,即点号也会匹配换行符\n;/i_大小写无关匹配;/x_加入空白符print "找到了!\n";
}
else{print "没找到!\n";
}

四、单词锚位

  默认情况下,给定的模式如果不匹配字符串的开头,就会顺移到下一个字符继续尝试。而通过给定锚位,可以让模式仅在字符串的指定位置匹配

  锚位并不局限于字符串首尾,还可应用于单词的首位,又称“整词匹配”。

锚位字符含义
脱字符(^)锚位\A表示字符串开头锚位(在字符集方括号中做取反用)
美元符($)锚位\z表示字符串结尾锚位
\b单词边界锚位,只匹配每组字符的开头或结尾
\B非单词边界锚位
$_ = "fred banny and fred";
if(/^fred/){ print "配上了\n";}else{ print "没配上\n";}    #^_在字符集外,该符号表示字符串的开头锚位
$_ = "fred";
if(/^fred$/){ print "配上了\n";}else{ print "没配上\n";}    #$符号表示字符串的结尾锚位$_ = "man fred man";
if(/\bfred\b/){ print "配上了\n";}else{ print "没配上\n";}  #\b表示单词的边界锚位,该例单词开头为f,结尾为d$_ = "search";
if(/$_ =~ \bsearch\B/){ print "配上了\n";}else{ print "没配上\n";}  #\B表示非单词边界锚位#绑定操作符(=~)——运用
$some_other = "I dream of betty rubble.";
if($some_other =~ /\brub/){ print "配上了\n";}else{ print "没配上\n";} 

编译运行:

配上了
配上了
配上了
没配上
配上了

五、绑定操作符(=~)

  默认情况下,模式匹配的操作对象是$_,绑定操作符(=~)告诉Perl,右边的模式是用来匹配左边的字符串,而不是匹配 $ _。当使用绑定操作符时,可以不使用默认变量 $ _,自由进行定义。如上例

六、模式中的内插

  正则表达式内部同样可以进行双引号形式的内插:下述代码中$what就等效于/^(Larry)/,也就是寻找Larry开头的行。

my $what = "Larry";
while(<>){if(/^($what)/){                                          #模式串中的内插print "We saw $what in beginning of $_";}
}

编译运行:

Larry and me                  #Larry开头
We saw Larry in beginning of Larry and me
Laty is good
larry
Larry is a good man           #Larry开头
We saw Larry in beginning of Larry is a good man
^Z

七、格式转换问题

  首行添加如下代码,将UTF-8格式的代码文件转换成GBK格式,在终端(GBK格式)导出,避免编译时乱码。

use encoding 'utf8', STDOUT=>'gbk';         #说明:采用的Perl版本为5.012, 支持encoding模式,如果是其它版本可能会出错

在这里插入图片描述

八、捕获变量

8.1、变量捕获及其存续期($1、$2 …

  圆括号可以用来进行分组,圆括号同样也可以用来进行捕获变量,这捕获变量保存的是字符串,在Perl里,它们的名称就是$1和$2这样的的形式,模式中有多少个捕获括号,就有多少个对应的捕获变量可用

  反向引用\2与捕获变量$2的区别

  • \2反向引用:指模式匹配期间得到的结果;
  • $2捕获变量:指模式匹配结束后对得到的捕获内容的索引。

  捕获变量的存续期:可存活到下次匹配成功为止。失败的匹配并不会改变上次成功匹配时得到的内容。

print "Hello\n";$_ = "Hello there, neigbor";
if(/\s(\w+),/){print "$1\n";                      #打印:there
}if(/(\S+) (\S+), (\S+)/){print "$1 $2 $3\n";                #打印:Hello there neigbor
}my $dino = "I fear that I'll be extinct after 1000 years.";
if($dino =~ /(\d*) years/){print "$1\n";                      #打印:1000
}

8.2、不捕获模式(?:

  正则表达式中的圆括号通常都会触发变量捕获,但是有时候却需要关闭这个功能,而仅仅是用它来进行分组。这就需要用到不捕获圆括号(?:)

$_ = "one two three four five";
if(/(\S+) (\S+) (\S+)/){             #?:_只用来分组,不用来捕获print "$2 $3\n";                  #打印:two three
}
**说明**:尽管上述打印结果未列出$1,但是第一个捕获变量还是要留给他$_ = "one two three four five";
if(/(?:\S+) (\S+) (\S+)/){                 #(?:)——只用来分组,不用来捕获print "$1 $2 $3\n";                      #打印:two three
}

8.3、命名捕获(?< Label >Pattern

  为了避免记忆$1之类的数字变量,Perl5.010增加了对捕获内容直接命名的写法。最终捕获到的内容会保存在特殊哈希%+里:其中的键就是在捕获时用的特殊标签,对应的值为被捕获到的字符串。具体的写法是:(?<Label>Pattern),其中Label可以自行命名

  在使用捕获标签后,反向引用的写法也会随之发生变化。之前所用的\1或者g{1}这样的写法,现在可以改为 \g{Label} 这样的写法,当然:k<Label>等效于\g{Label}

my $names = "Fred or Barney";
if($names =~ /(?<name1>\w+) (?:and|or) (?<name2>\w+)/){   #?<>_命名的捕获#print "$1, $2\n";print "$+{name1}, $+{name2}\n";                         #打印: Fred, Barney
}my $names = "Fred Flinstones and Wilma Flinstones";
if($names =~ /(?<last_name>\w+) and \w+ \g{last_name}/){  #在反向引用中使用命名变量,也可改g{}为k<>print "$+{last_name}\n";                                 #打印:Flinstones
}

8.4、自动捕获变量( $&、 $’、 $`

  Perl中三大免费的自动捕获变量:

  1. $& :匹配区段内容
  2. $’ :匹配区段之后的内容
  3. $` :匹配区段之前的内容。
$_ = "one two three, four five six";
if(/\s(\w+),/){print "$1\n";print "$&\n";       #自动匹配字符变量(捕获全部匹配到的)print "$'\n";       #单引号(捕获匹配节点后面的其余字符串)print "$`\n";       #反引号(捕获匹配节点前面的其余字符串)print "$`$&$'\n";   #组合(完整子符串)print "$`<$&>$'\n"; #尖括号(标识出捕获到的字符串部分)
}

编译运行:

threethree,four five six
one two
one two three, four five six
one two< three,> four five six

九、模式测试程序

  正则表达式测试程序:

#这是一个模式测试程序
while(<>){chomp;if(/我的正则表达式/){                              #    \s\d+print "配上了:|$`<$&>$'|\n";  }else{print "没配上\n";}
}

编译运行:(正则表达式:/\s\d+/)

i have 100 dollars                    #键入
配上了:|i have< 100> dollars|        #打印结果
the number is 1245
配上了:|the number is< 1245>|

这篇关于(八) 正则表达式——基础介绍(元字符、模式分组、单词锚位/b、模式匹配操作符(m//)与修饰符/isx、捕获变量等)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/434692

相关文章

SpringValidation数据校验之约束注解与分组校验方式

《SpringValidation数据校验之约束注解与分组校验方式》本文将深入探讨SpringValidation的核心功能,帮助开发者掌握约束注解的使用技巧和分组校验的高级应用,从而构建更加健壮和可... 目录引言一、Spring Validation基础架构1.1 jsR-380标准与Spring整合1

Python中使用正则表达式精准匹配IP地址的案例

《Python中使用正则表达式精准匹配IP地址的案例》Python的正则表达式(re模块)是完成这个任务的利器,但你知道怎么写才能准确匹配各种合法的IP地址吗,今天我们就来详细探讨这个问题,感兴趣的朋... 目录为什么需要IP正则表达式?IP地址的基本结构基础正则表达式写法精确匹配0-255的数字验证IP地

Pytest多环境切换的常见方法介绍

《Pytest多环境切换的常见方法介绍》Pytest作为自动化测试的主力框架,如何实现本地、测试、预发、生产环境的灵活切换,本文总结了通过pytest框架实现自由环境切换的几种方法,大家可以根据需要进... 目录1.pytest-base-url2.hooks函数3.yml和fixture结论你是否也遇到过

Mysql如何将数据按照年月分组的统计

《Mysql如何将数据按照年月分组的统计》:本文主要介绍Mysql如何将数据按照年月分组的统计方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录mysql将数据按照年月分组的统计要的效果方案总结Mysql将数据按照年月分组的统计要的效果方案① 使用 DA

mysql的基础语句和外键查询及其语句详解(推荐)

《mysql的基础语句和外键查询及其语句详解(推荐)》:本文主要介绍mysql的基础语句和外键查询及其语句详解(推荐),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋... 目录一、mysql 基础语句1. 数据库操作 创建数据库2. 表操作 创建表3. CRUD 操作二、外键

Python基础语法中defaultdict的使用小结

《Python基础语法中defaultdict的使用小结》Python的defaultdict是collections模块中提供的一种特殊的字典类型,它与普通的字典(dict)有着相似的功能,本文主要... 目录示例1示例2python的defaultdict是collections模块中提供的一种特殊的字

Python基础文件操作方法超详细讲解(详解版)

《Python基础文件操作方法超详细讲解(详解版)》文件就是操作系统为用户或应用程序提供的一个读写硬盘的虚拟单位,文件的核心操作就是读和写,:本文主要介绍Python基础文件操作方法超详细讲解的相... 目录一、文件操作1. 文件打开与关闭1.1 打开文件1.2 关闭文件2. 访问模式及说明二、文件读写1.

Linux系统配置NAT网络模式的详细步骤(附图文)

《Linux系统配置NAT网络模式的详细步骤(附图文)》本文详细指导如何在VMware环境下配置NAT网络模式,包括设置主机和虚拟机的IP地址、网关,以及针对Linux和Windows系统的具体步骤,... 目录一、配置NAT网络模式二、设置虚拟机交换机网关2.1 打开虚拟机2.2 管理员授权2.3 设置子

C#基础之委托详解(Delegate)

《C#基础之委托详解(Delegate)》:本文主要介绍C#基础之委托(Delegate),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. 委托定义2. 委托实例化3. 多播委托(Multicast Delegates)4. 委托的用途事件处理回调函数LINQ

SpringBoot如何通过Map实现策略模式

《SpringBoot如何通过Map实现策略模式》策略模式是一种行为设计模式,它允许在运行时选择算法的行为,在Spring框架中,我们可以利用@Resource注解和Map集合来优雅地实现策略模式,这... 目录前言底层机制解析Spring的集合类型自动装配@Resource注解的行为实现原理使用直接使用M