本文只是关于正则一些容易出错的地方,关于正则的学习,可参考如下两篇文章:

基础正则:https://www.cnblogs.com/f-ck-need-u/p/9621130.html

Perl正则:https://www.cnblogs.com/f-ck-need-u/p/9648439.html

1.正则中所有的匹配模式,都应该理解为"匹配了某字符或字符串后,紧跟着再匹配"。这个概念很重要。

2.中括号首部使用脱字符时,表示的是紧跟着匹配不含给定字符的字符,而不是允许不匹配给定的字符。
它们大多数时候是等价的,但在匹配行尾时,意义不同,例如:Aa[^bcd]$ 所匹配的行允许是Aaa$或Aax$,但不允许仅是Aa$。
这就是正则中"紧跟着匹配"的意思。

3.(\.[0-9]+)? 可匹配小数点部分,不能写成 (\.?[0-9]*) ,后者即使不能匹配小数点,也能匹配原本处于小数点后的数值

4.星号*匹配问题0或多个字符,如果写成"a*",将可以匹配任何单个字符,只不过对于非a字符,匹配到的结果为空。

例如字符串"111aaaAAA",正则"1a*"其实从读取第2个字符进行匹配的时候就已经匹配完成了,匹配的结果不是"1aaa",而是"1"加上1前面的一个空,因为是从行首这个锚定位开始匹配的。使用sed或perl进行替换操作就很容易理解。

$ echo '111aaaAAA' | perl -lne 'print s/a*/b/rg'
b1b1b1bbAbAbAb        # 每一个非a字符前都被替换了$ echo '111aaaAAA' | perl -lne "/1a*/;print $&;print $'"
1                   # 表示匹配到的内容
11aaaAAA       # 表示匹配后剩下的内容

这可能不是很好理解。但其实想想".*"的作用,其实他们是同一类的写法,正如".*"并不是先用点去匹配一个字符后再通过星号去重复这个字符,而是直接表示匹配可能任意多个的任一字符。不同之处在于,".*"匹配任何单个字符,而"a*"匹配任何单个字符,包括空位置。

另外,有些语言在处理正则的方式上有些差异,特别是在测试"a*"的时候,grep/sed/perl均有所不同,不过python/perl/ruby之类的语言在处理这个问题上,结果都一样。

5.perl正则括号分组时,使用(?:替代左括号(,可以表示只分组不捕获。所谓的捕获表示的是可以反向引用或保存到正则外部的变量中
([-+]?[0-9]+(\.[0-9]+)?) *(cm|mm) :(cm|mm)将保存为$3
([-+]?[0-9]+(?:\.[0-9]+)?) *(cm|mm) : (cm|mm)将保存为$2

6.特殊锚定符,锚定所匹配的是位置,而非字符,行首^和行尾$同样如此。
注意某些程序对单词的理解和边界定义不一样。且有些程序并不完全支持下列所有的特殊元字符。一般来说,单词是由字母、数字和下划线组成的,即[a-zA-Z0-9_]。
例如gnu grep 2.6版本就不支持\s和\d,而gnu grep 2.20支持\s但不支持\d
'\b':匹配单词边界处的空字符Match the empty string at the edge of a word.
'\B':匹配非单词边界处的空字符Match the empty string provided it's not at the edge of a word.
'\<':匹配单词开头处的空字符Match the empty string at the beginning of word.
'\>':匹配单词结尾处的空字符Match the empty string at the end of word.
'\w':匹配单词构成部分Match word constituent, it is a synonym for `[_[:alnum:]]'.
'\W':匹配非单词构成部分Match non-word constituent, it is a synonym for `[^_[:alnum:]]'.
'\s':匹配空白字符Match whitespace, it is a synonym for `[[:space:]]'.
'\S':匹配非空白字符Match non-whitespace, it is a synonym for `[^[:space:]]'.
'\d':匹配数字it is a synonym for `[0-9]'.
'\D':匹配非数字it is a synonym for `[^0-9]'.

For example, '\brat\b' matches the separate word 'rat', '\Brat\B' matches 'crate' but not 'furry rat'.

7.字符类,注意某些程序并不完全支持下列所有的字符类
'[:alnum:]' :same as '[0-9A-Za-z]'.
'[:alpha:]' :'[:lower:]' and '[:upper:]', same as '[A-Za-z]'.
'[:lower:]' :
'[:upper:]' :
'[:digit:]' :'0 1 2 3 4 5 6 7 8 9'.
'[:xdigit:]' :Hex digits: `0 1 2 3 4 5 6 7 8 9 A B C D E F a b c d e f'.

'[:blank:]' :space and tab.
'[:space:]' :tab, newline, vertical tab, form feed, carriage return, and space.
'[:punct:]' :Punctuation characters; this is '! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~'.
'[:print:]' :'[:alnum:]', '[:punct:]', and space.
'[:graph:]' :Graphical characters: '[:alnum:]' and '[:punct:]'.

'[:cntrl:]' :Control characters. octal codes 000 through 037, and 177 (`DEL').

8.同一个表达式中,被匹配过的字符无法被第二次匹配。因为正则的宗旨是:匹配了某字符或字符串后,紧跟着再匹配。
例如字符串"#c#",正则表达式"(#.)(.#)"无法匹配。
再例如字符串"#cc#",正则表达式"(#.)(.*)(.#)"能匹配成功,只不过第二个分组只能匹配空。

9."环视"锚定,即lookaround anchor(也称为"零宽断言",表示匹配的是位置,不是字符)。
以 (?= 替代左括号表示从左向右的顺序环视,例如(?=\d)表示当前字符的右边是一个数字时就满足条件
以 (?<= 替代左括号表示从右向左的逆序环视,例如(?<=\d)表示当前字符的左边是一个数字时就满足条件

  • 正向环视:(?=...)和(?!...),感叹号表否定,即无法匹配感叹号右边的字符时才捕获。
  • 逆向环视:(?<=...)和(?<!...)

逆向环视的表达式必须只能表示固定长度的字符串,例如(?<=word)或(?<=word|word)可以,但(?<=word?)不可以,因为?匹配0或1长度,长度不定。
在PCRE中,可重写为(?<=word|words),但perl中不允许,因为perl严格要求长度必须固定。

10.关于"环视"锚定,最需要注意的一点是匹配的结果不占用任何字符,它仅仅只是锚定位置。
例如:your name is longshuai MA 和 your name is longfei MA
使用(?=longshuai)将能锚定第一个句子中单词"longshuai"前面的空字符,但它的匹配结果是"longshuai"前的空白字符,
所以(?=longshuai)long才能代表"long"这几个字符串
所以仅对于此处的两个句子,long(?=shuai)和(?=longshuai)long是等价的

11.贪婪匹配、惰性匹配和占有优先匹配
默认情况下,对于重复次数的表达式都是贪婪匹配,表示尽可能多的匹配。
有些高级正则引擎支持惰性匹配,表示尽可能少的匹配,只要能满足条件就立即停止。

  • *、    +、    ?、     {M,N} :都是贪婪匹配(greedy)
  • *?、  +?、  ??、   {M,N}? :都是惰性匹配(lazy,Reluctant)
  • *+、  ++、  ?+、   {M,N}+ :都是占有优先匹配(possessive)

占有优先和固化分组是相同的,只要占有了就不再交换,不允许进行回溯。示例见下面的(?>...)固化分组方式

12.匹配模式

  • (?i):不区分大小写,可使用(?-i)取消该模式。例如"(?i)abc(?-i)cdB"只对中间的abc进行不区分大小写的匹配

    • 由于(?i)遇到闭括号就失效,可以将需要不区分大小写匹配的部分写入分组括号中,例如"((?i)abc)cdB",(?:(?i)abc)cdB=(?i:abc)cdB
  • (?x):extend模式,将忽略多个连续空格和注释符到行尾的字符
  • (?m):(multiline)多行模式,改变^和$的匹配模式。默认模式下,它们匹配字符串首部和尾部。此模式下:
    • ^将匹配字符串首部和换行符。若要仅匹配字符串首部,使用\A。
    • $将匹配字符串尾部、换行符和换行符前的空字符。若要仅匹配字符串尾部和行尾,使用\Z,若要仅匹配字符串尾部,使用\z
  • (?s):(singleline或dotall)单行模式,改变"."的匹配模式,默认模式下,点"."无法匹配换行符,dotall模式下可以
  • (?U):lazy匹配模式。默认是greedy匹配。

13.强制字面解释:\Q...\E。该序列将其中间的所有字符强制解释为字面符号,强制性极强。
但perl和pcre有所不同。perl中,该序列中间可引用变量进行变量替换,而pcre中变量符号也被当作普通字符。

14.普通分组和捕获

  • (),$1,$2,$3,$4...有些地方使用\1,\2,\3,\4,sed中使用&表示所有匹配,perl中则使用$&
  • \g1,\g2,\g3或\g{1},\g{2},\g{3}。

其中$1,$2, ...用于正则外面,而"\g1", "\g2", ... 用于正则内部

15.命名分组和捕获

  • (?:...):非命名捕获,仅用于分组,不可用于引用,也称为非捕获型括号。例如"(1|one)(?:2|two)(3|three)",$1=(1|one),$2=(3|three)
  • (?<NAME>...):命名捕获,分组捕获后还命名,就像变量赋值一样。可以使用\k<NAME>或\k'NAME'或\g{NAME}的方法来引用
  • (?>...):固化分组。一匹配成功就永不交回内容(用回溯的想法理解很容易)。

例如"hello world"可以被"hel.* world"进行匹配,但不能被"hel(?>.*) world"匹配。
因为正常情况下,".*"匹配到所有内容,然后回溯释放已匹配内容直到空格" "字符。而固化分组后,已匹配的内容绝不交回,也就无法回溯。

16. 重置匹配:\K 用于重置匹配的位置。
比如,foot\Kbar 匹配”footbar”,但是得到的匹配结果是 ”bar”。但是, \K 的使用不会干预到子组内的内容, 比如 (foot)\Kbar 匹配 ”footbar”,第一个子组内的结果仍然会是 ”foo”。

$ echo abc123abcfoo | grep -P -o '(abc)123\K\g1foo'
abcfoo

17.要想对一个字符串匹配后取反。可以通过正向环视锚定取反来间接实现。
例如,"-a -3 ac c 3 b"中取出负数、正数和空格很简单,"-?[0-9]+|\s"即可,但想要借此取反得到"-a ac c b",目前正则表达式只能通过(?!)的环视取反实现:"((?!-?[0-9]+|\s).)*",外层括号表示右边不是正数、负数或空格的字符都匹配并进行分组,然后重复量词*,将连续的内容连接起来。
例如:

echo "-a -3 ac c 3 b" | grep -P '((?!-?[0-9]+|\s).)*'

...

转载于:https://www.cnblogs.com/f-ck-need-u/p/7684762.html

pcre和正则表达式的误点相关推荐

  1. VisualFreeBasic的pcre/pcre2正则表达式修复

    VisualFreeBasic中使用CRegex其实就是vbscript里面的正则,性能比较弱 同时在他的文件头库里面分别有pcre两个版本的bi头文件 只是对应的库没有加进来,本人的主要目的,就是记 ...

  2. nginx(五十三)nginx中使用的PCRE正则

    一   pcre 正则语法 说明: 1)从'在nginx中'使用符合'PCRE风格'正则的角度上'学习'2) 部分'案例'比较冷门,不具有'实际'生产意义 PCRE汇总 ①  元字符 说明: 通过'\ ...

  3. 正则表达式学习神器!

    推荐一款优秀的正则表达式在线可视化工具 我相信很多朋友第一次听到正则表达式时,都感觉这是一个高大上的名词. 其实,简单来说,正则表达式就是用来匹配文本的. 正则表达式里的 "正" ...

  4. 4.PHP正则表达式与数组

    PHP正则表达式相关 行定位符 开头 ^tm 结尾 tm$ 不限制 tm 单词定界符 \btm\b   单词tm,如果想取反的话就是大写的 \Btm\B 或的关系,[Tt][Mm] 可以表达 tm T ...

  5. PCRE接口pcre_fullinfo混合子模式调用结果

    NGINX中使用PCRE最为正则表达式的解析接口,对编译和解析过程中的一些点进行了测试验证 PCRE接口pcre_fullinfo()的描述在这个链接中有详细的描述,这里对接口的一些 链接 http: ...

  6. 编程语言和shell编程的基础内容以及grep、egrep命令及相应的正则表达式和用法...

    bash的特性之多命令执行的逻辑关系: 1.命令替换 COMMAND1 $(COMMAND2) 2.管道 COMMAND1 | COMMAND2 | COMMAND3 ... 3.顺序执行结构 COM ...

  7. 梳理正则表达式发展史

    作者:kamly,腾讯 CDC 应用开发工程师 前言 正则表达式在我们日常的软件开发过程中被广泛使用,例如编写 Nginx 配置文件.在 Linux 与 macOS 下查找文件,然而不同软件不同操作系 ...

  8. php正则表达式 ( ),PHP正则表达式(超详细)

    正则表达式,从入门到放弃. 我太难啦~~~~~ 一段时间没用,基本就全忘光了,所以学习要养成作笔记的习惯,卑微的我这不就来开始补做笔记写博客啦. 介绍 PHP支持两种风格的正则表达式语法: POSIX ...

  9. Saltstack自动化环境部署

    Saltstack知多少 Saltstack是一种全新的基础设施管理方式,是一个服务器基础架构集中化管理平台,几分钟内便可运行起来,速度够快,服务器之间秒级通讯,扩展性好,很容易批量管理上万台服务器, ...

最新文章

  1. 数字货币 区块链 双花攻击 Double Spend Attack 简介
  2. java元婴期(22)----java进阶(mybatis(1)---mybatis框架概述入门程序)
  3. POJ1753 棋盘翻转(位压缩+广度优先搜索)
  4. 国庆中秋活动——让孩子亲近数学并爱上数学:《数学小侦探》来袭(来自科大出版社的福利)
  5. php 电梯程序设计,教你写出京东电梯式轮播
  6. 企业实战_09_MyCat 搭建Mysql 一主三从复制环境
  7. 7.hdfs工作流程及机制
  8. springmvc获取配置文件的值使用$这个符号
  9. 如何自己实现一个缓存服务
  10. linux操作系统实训心得总结,操作系统实验报告心得体会
  11. ArcGIS教程 - 3 ArcGIS快速入门
  12. [安卓相机1]简单小Demo
  13. sklearn入门——逻辑回归
  14. mysql innodb文件存储_MySQL数据库和InnoDB存储引擎文件
  15. 自动生成图片及修改图片尺寸
  16. HPE牵手CSC,打造DXC延承HP百年家规
  17. Python爬虫+BI分析,做一份酷炫的A股牛市可视化!
  18. 基于eNSP中大型校园/企业网络规划与设计_ensp综合大作业(ensp综合实验)
  19. 万能显卡驱动win7_使命召唤:战区442.59驱动介绍
  20. 娃娃机的秘密:你为什么总是抓不到娃娃?

热门文章

  1. wxpython textctrl_wxpython中Textctrl回车事件无效的解决方法
  2. 360浏览器升级_360安全卫士下载|360安全卫士 12.0 最新版
  3. javax.net.ssl.SSLException: java.lang.RuntimeException: Could not generate DH keypair
  4. Apache Dubbo是一款高性能Java RPC框架。
  5. 获取mysql系统时间
  6. HBase: HMaster服务自动停止,且关闭集群时HRegionserver无法关闭的问题解决
  7. my-innodb-heavy-4G.cnf中文注释(主要配置文件注释)
  8. Android:数据持久化、Environment、SharedPreferences、内部存储internalStorage
  9. 如何让政府性论坛外链最大利益化
  10. 内容管理系统(CMS)的设计和选型