• 正则表达式 自学笔记整理记录 EASY REGEX~


    整理正则表达式篇
                                                                                         -wuian7yulian

     


     


     

    基础知识介绍 : 

    • 1> 字符串的组成:

    对于字符串"ABC"来说,其包括三个字符 四个位置
    可以理解为 三个人已经排好队 这样 再来一个人排队就有四个位置可以选择

    • 2> 什么是占有字符:

    正则表达式匹配过程中,如果子表达式匹配到东西,而并非是一个位置,并最终保存匹配结果当中,就成为占有字符

    • 3> 什么是零宽度:

    正则表达式在匹配过程中,如果子表达式匹配一个位置,或者匹配的内容并不保存到匹配结果当中,这种就称作零宽度

    • 4> 占有字符和零宽度的区别:

    占有字符是互斥的,而零宽度是非互斥的,即: 一个字符同一时间只能由一个子表达式进行匹配,但是一个位置 就可以由多个零宽度的子表达式匹配

    • 5> 匹配控制权:

    正则表达式由左到右依次进行匹配,通常情况下是有一个表达式取得控制权的

    • 6> 匹配规则:

    (正确的理解零宽度)
    以"ABC"为例子 :
    分析:"ABC"有三个字符但是有四个位置 比如说A前面的位置是 location1, A和B中间是location2 ..C后面就是location4
    那么 分析一个正则 reg="AC"; 它去和字符串匹配
    过程为:
    首先是reg的子表达式 即 : "A"
    现在是"A"(正则表达式的)[后 称为 A(正)] 取得了控制权 从字符串(从左向右)的 位置 location1 进入字符串,向右遇到一个A字符,匹配成功,于是就把源数据中的A存放到结果当中(占位字符),表明它占有了一个字符,而接下来 就将控制权转交给了C(正),注意!!! 现在C(正)的进入位置就成了location2!!从这开始发现后面字符是B,匹配失败
    再分析一个零占位的reg reg="^A";
    ^进入字符串位置 location1 匹配成功 A(正)获得控制权 进入字符串位置 仍然为location1 这就是零占位大概的原理
    他们两个的区别就为: 一个是越过了字符(或者认出字符) 一个根本不是匹配字符(而是匹配他们中间的位置)

    • 7> 元字符:

    -----元字符--||----------描述-------------------------
    . || 匹配 除换行符以外的任意字符
    w || 匹配 字母数字或下划线或汉字
    s || 匹配 任意空白符
    d || 匹配 数字
     || 匹配 单词开始或者结束,(匹配的是位置)
    ^ || 匹配 字符串开始
    $ || 匹配 字符串结束
    ------------------------------------------------------

    • 8> 转义字符:

    如果想要得到元字符本身的话 需要使用"" 来取消这些元字符的特殊意义
    "wahsdwaskdhk" 如果我想匹配这个字符串中的wa
    那么:
    在js(不需要进行编译的语言)中 正则可以写成:"\wa"
    在java中(需要先由编译器解析的语言)中 需要写成"\\wa"

    原因:正常情况下 编译语言 需要先解析一次这个字符串 而java中的也是转译符号
    我们要用一个的话 就需要写\ 这样才识别
    即上面那句"\\wa" 经过编译器后就成为了"\wa" 所以最终的正则表达式识别的就是这个

    • 9> 字符类:

    字符类就是指使用"[]"括起来的 是严格区分大小写的
    需要注意的是仅仅是匹配一个! 唯一匹配一个
    例1: [osP] 就是匹配其中的一个o或者s或者P
    例2: [a-zA-z0-9]就是匹配一个任意大小写字符或者数字

    • 10> 限定符:

    ----限定符----||----------Description-------------------------
    前面紧挨着的正则匹配
    * || 重复 0次 或 多次
    + || 重复 1次 或 多次
    ? || 重复 0次 或 1次
    {n} || 重复 n次
    {n,} || 重复 n次 到 +∞
    {n,m} || 重复 n次 到 m次 -闭区间
    ------------------------------------------------------

    • 11> 分支条件:

    用"|"把不同的规则进行分割
    或者的关系 | 前后都是两个完整的表达式
    注意点: 分枝条件的顺序 正则表达式从左向右依次匹配 若满足了某个分支 就不会再管其他分支了

    • 12> 分组:

    可以使用()小括号来指定表达式 小括号里面的代表一组
    例: (d{1,3}){3} 就是d{1,3}重复了三次

    • 13> 翻译字符:

    ----表达式----||----------Description-------------------------
    W || 匹配任意一不是字母数字下划线的字符
    S || 匹配任意一个不是空白字符的字符
    D || 匹配不是数字的字符
    B || 匹配不是单词开头或者结尾的位置
    [^X] || 匹配除了X意外的任意字符
    [^a-z] || 匹配除了小写字母意外的任意字符
    [^aeixy] || 匹配除了aeixy意外的任意字符
    ------------------------------------------------------

    • 14> 后向引用:

    使用小括号指定一个子表达式后,匹配这个子表达式的文本(也就是分组捕获的内容)做进一步处理,默认情况下 每个放入怒都会自动拥有一个组号
    规则是:从左向右,以分组的左括号为标志第一个出现的分组的组号为1 第二个为2
    其他规则:
    1) 分组号为0的是对应整个正则表达式
    2) 组号分配过程是要对正则表达式扫描两遍的:第一遍只给未命名组进行分配组号,第二遍只给已经命名的组分配
    所以所有命名组的组号都大于未命名的组号
    3) 也可以使用(?:exp)这样的方式来限制一个分组对组号的分配的参与权
    --
    后向引用的概念 后向引用用于重复搜说前面某个分组匹配的文本 1代表分组1匹配的文本
    例: 正则表达式为(a)(b)(c)2 匹配 abcb 成功
    他们的分组号分别为 1 2 3 2代表第二组匹配到的文本

    取消组号例: reg=(?<g1>abc)(?<g2>cde)(?:d{3})
    原文本: test=abccde298
    原理: 首先扫描reg的组 以左括号为基准一共有三个组 而且前两个组已经分配了组名,只有最后一个没有分配组名,即为未命名的组 规则是献给未命名的组进行分配组号但是改组用了(?:exp)来避免了组号分配所以说他没有组号 然后给命名的组进行分配组号 分表为$1 $2 且整个正则的组号为$0

    • 15> 零宽断言和负零宽断言:

    ----------------------------------------------------
    ||(exp) ||匹配exp并捕获文本到自动命名的组里
    捕获 ||(?<name>exp) ||匹配exp并捕获文本到名称为name的组里
    ||(?:exp) ||匹配exp不捕获匹配文本也不给分组分配组号
    ----------------------------------------------------
    ||(?=exp) ||匹配exp前面位置但是不匹配exp
    断言 ||(?<=exp) ||匹配exp后面位置但是不匹配exp
    ||(?!exp) ||匹配后面不是exp的位置但是不匹配exp
    ||(?<!exp) ||匹配前面不是exp的位置但是不匹配exp
    ----------------------------------------------------
    注释 ||(?#comment) ||注释
    ----------------------------------------------------

    • 16> 零宽度断言:

    1. (?=exp) :
    也叫零宽度正预测先行断言,她匹配自身出现的位置后面能匹配表达式exp
    注意预先这个词组 比如 我们匹配"asdhaking"
    正则为w+(?=king) 匹配结果为asdha
    原理为: 第一步到 a字符前面的位置w匹配上他会看一下后面是king吗 只是看一下 并不做结果捕捉获取 然后继续向后 依次类推到a的时候看到后面是king 则匹配结束 返回前面匹配内容
    2. (?<=exp) :
    又叫零宽度正回顾断言,它匹配自身出现位置的前面匹配表达式exp
    例 reg = (?<=ing)d{3} test="123inging123123"
    结果为中间的123

    • 17> 负向零宽断言:

    1. (?!exp) :
    零宽度负预测先行断言
    断言此位置后面跟的不能匹配表达式exp
    2. (?<!exp) :
    零宽度负回顾断言
    断言此位置前面跟的不是exp的位置

    • 18> 平衡组:

    ----------------------------------------------------
    ||(?'group') || 把捕获的内容密码为group,并压入堆栈
    ||(?'-group') || 从堆栈上弹出最后压入堆栈名为group的捕获内容
    ||如果堆栈为空在本组匹配失败
    ||(?'group'yes|no) || 如果堆栈上存在名为group的捕获内容的话,
    ||继续匹配yes部分的表达式,否则匹配no表达式
    ||(?!) || 零宽度负先行断言 由于没有后缀表达式,试图匹配总是失败
    ----------------------------------------------------
    压栈: (?'t1'123)(?'t1'456) 对应123456
    group组(栈(先进后出)) 显示的数据就是456
    弹栈: (?'t1'123)(?'t1'456)(?'-t1') 对应123456
    group组 压了两次栈 第一次压入文本123 第二次压入456 然后弹出一次数据 则显示123

    (?(group)yes|no)
    栈的使用中我们无法预测栈是否已经到栈底 这个正则解决了这个问题 意义为 若 栈空 -> no 表达式
    若 未空 -> yes 表达式
    例 (?'t1'123)(?'t1'456)(?'-t1')(?(t1)1|2)
    匹配 12345611234562
    匹配到的是1234561
    而(?'t1'123)(?'t1'456)(?'-t1')(?'-t1')(?(t1)1|2)
    匹配到的是1234562

    • 19> 贪婪与非贪婪:

    以上例子实际上我们都是用的贪婪模式
    例: (123).+25 对用匹配1235252525
    匹配结果为 1235252525 全部匹配到 而实际上我们常认为应该是123525

    首先 贪婪和非贪婪是对!!子表达式!!的匹配行为指定添加的概念!!!

    贪婪模式: 在整个表达式匹配成功的前提下尽可能多的匹配 (子表达式匹配内容尽可能靠后)
    非贪婪模式: ...尽可能少的匹配


    非贪婪模式限定符 带问号?的限定符
    -------------------------------------------------------------
    *? | 匹配上一个元素 零次或多次,但次数尽可能少
    +? | 匹配上一个元素 一次货多次,但次数尽可能少
    ?? | 匹配上一个元素 零次或者一次,但..
    {n}? | 匹配前导元素 恰好n次
    {n,}? | 匹配上一个元素 至少n次,但次数..
    {n,m}? | 匹配上一个元素次数介于n到m次之间,但次数..
    --------------------------------------------------------------

    • 20> 贪婪匹配和非贪婪(懒惰)匹配原理

    非贪婪模式只被部分NFA引擎所支持 控制权的问题
    未完全深入理解 待后期研究

     





     

    易错笔记本:

    • 21> 正则表达式出错引发注意点        有在使用中犯错的地方 感觉需要注意的点 我会在这更新

    1 正则取组名必须要使用单引号
    2 匹配目标是的话 是必须需要转译的
    3 分组中每个都是单个 组中 [1sa] 就是1或者s或者a 但是[ad]就不再是了 是代表a或者数字
    4 如要匹配括号 纯字符硬匹配的话 必须需要写成( 中括号也一样 因为正则的字符用到了 相当于关键字 有意义
    而实际上在分组中[a(s] 是能匹配到(的 相当于a或者或者s 但是建议用转译字符转译一下 以防与外部正则表达式错误配对
    --4.18日更


    参考文件:
    http://www.cnblogs.com/deerchao/archive/2006/08/24/zhengzhe30fengzhongjiaocheng.html#mission

  • 相关阅读:
    oracle中去掉文本中的换行符、回车符、制表符
    oracle中的exists和not exists和in用法详解
    将异常(getStackTrace)转化成String
    树的深度优先遍历和广度优先遍历的原理和java实现代码
    extjs4.0 treepanel节点的选中、展开! 数据的重新加载
    揭秘对象
    JVM由浅入深
    语法糖
    Java的技术体系结构
    菜鸟笔记 -- Chapter 09 常见类和接口
  • 原文地址:https://www.cnblogs.com/wunian7yulian/p/5403822.html
Copyright © 2020-2023  润新知