美文网首页
读《精通正则表达式》

读《精通正则表达式》

作者: JLUiceman | 来源:发表于2019-03-06 23:10 被阅读0次

    todo:提取要点,梳理结构图

    第一章

    1. ^脱字符

    2. 正则表达式结构体(字符组)即=> [ ],只有在字符组内部且不是出现在头部,连字符(-)才是元字符,其他的元字符(脱字符除外)在字符组内部均为普通字符, 同时需要注意字符组只是匹配一个字符(和()多选结构区分开)

    3. 排除型字符组表示的是"匹配一个未列出的字符"而非"不要匹配列出的字符",即是一种肯定断言,即使名字里包含了“排除”两个字,它仍然需要匹配一个字符

    4. 一个字符组只能匹配目标文本中的单个字符,而每个多选结构自身都可能是完成的正则表达式,都可以匹配任意长度的文本

    5. < 和 > 用于匹配单词的开头和结束位置(eg: <cat 匹配以cat开头的单词),<和>本身不是元字符,只有与反斜线结合时才是元字符(js不支持,可用\b元字符替代)

    6. 可选项元素=> ? 与其他元字符不同,只作用于之前紧邻的元素or多选结构(即括号),表示此处容许出现或不出现这个字符

    7.其他量词: + 表示之前紧邻的元素出现一次或多次; * 表示之前紧邻的元素出现任意多次获不出现;{ x, y} 表示之前紧邻的元素出现x-y之间的次数

    8.反向引用: 允许匹配与表达式先前部分匹配的同样的文本(实测js实现的正则引擎不支持),用下划线+数字来表示(eg: ([a-z])(0-9)\1\2, \1表示[a-z]匹配的内容,\2表示[0-9]表示的内容)

    9.转义符:\ 无需多言

    10.常用的正则例子:

    作用 正则
    匹配变量名 [a-zA-Z_][a-zA-Z_0-9]*
    引号内的字符串 "[^"]*"
    金额 $[0-9]+(.[0-9][0-9])?

    11. 我觉得挺有道理的一句话:字节如何解释只是视角(或称作编码更合适些)的问题


    第二章 (入门示例拓展)

    1.一些Perl的tip:

    命令 含义
    m/正则/ 对该正则进行匹配
    =~ 连接正则表达式和待搜索的目标字符串

    2. 用()来分组和捕获,用(?:)表示只分组不捕获·

    3. 注意(x|y) 和[xy]*的区别

    4. 字符组的子语言的规范不同于正则表达式主体,元字符的的定义在正则表达式中并不是统一的(eg: \b)

    5. 一些元字符的简记法

    元字符 含义
    \t 制表符
    \n 换行符、
    \r 回车符
    \s 任何空白字符
    \S 任何非空白字符
    \w [a-zA-Z0-9]
    \W 除\w以外的字符
    \d [0-9]
    \D 非数字字符

    6.Perl中使用1,2,$3....之类的变量来保存()分组匹配到的值,可以通过这种方法从字符串中提取信息

    7.一种保留两位or三位小数(根据第三位是否非0)的正则表达式(Perl版本): s/(.\d\d[1-9]?)\d*/$1/

    js版本: const reg = /(.\d\d[1-9]?)\d*/; const string = string.replace(reg, RegExp.$1)

    8. "环视"结构不匹配任何字符,只匹配文本中的特定位置

    顺序环视(从左往右): (?=正则)
    逆序环视(从右往左): (?<=正则)
    eg: 正则为: (?=Jeffrey)Jeff, 则Jeffrey可以匹配,Jeffrex不能匹配,尽管环视结构并不匹配任何字符

    使用环视替换字符: Jeffs => Jeff's 则可以使用(perl语法)s/(?<=\bJeff)(?=s\b)/'/g(即找到这样一个位置: 紧接在Jeff之后,在s之前,将其替换为')

    使用环视完成数字每三位插入一个逗号(16777272 => 16,777,272): s/(?<=\d) (?=(\d\d\d)+$)/,/g(即寻找这样的位置:左侧为数字,右侧为3的倍数个数字)

    9. 其他环视

    类型 正则表达式 匹配成功的条件
    肯定逆序环视 (?<=.....) 子表达式能够匹配左侧文本
    否定逆序环视 (?<!.....) 子表达式不能够匹配左侧文本
    肯定逆序环视 (?<=.....) 子表达式能够匹配右侧文本
    肯定逆序环视 (?<!.....) 子表达式不能够匹配右侧文本

    用环视表示\b(单词分界符)=> (?<!\w)(?=\w)|(?<=\w)(?!\w)

    第三章(正则表示的特性和流派概览)

    1.正则表达式的起源: 20世纪40年代的两位神经学家(Warren MCCulloch & Walter Pitts) => 数学家(Stephen Kleene)在代数中正式描述为"正则集合"

    2.正则相关的工具:

    • qed => ed(后发展为Unix中的ed编辑器)
    • ed的"g/Regular Expression/p"最终成为独立的工具grep
    • AT&T贝尔实验室的Alfred Aho写出了egrep

    3.字符编码: 本质上是一种写明的共识,它规定了不同数值的字节应该如何解释,相同的字节用于不同的编码所代表的值可能不同

    4.编码应该考虑的点

    • 程序能否识别这种编码
    • 程序如何决定采用哪种编码来处理这些数据
    • 正则表达式对这种编码的支持程度如何

    5.正则表达式编码支持程度应该考虑的点

    • 是否能够支持多字节字符?eg: 点号(.)和[^x]之类的表达式是匹配单个字符还是单个字节?
    • \w,\d,\s之类的元字符 ,是否额能够识别编码中的所有字符?eg:é亦是字符,此时能否匹配
    • 程序是否会扩展对字符组的解释?eg: [a-z]能否匹配é
    • 不区分大小写的匹配是否对所有字符有效?eg:é

    6.Unicode相关

    • 从基本的意义上说,Unicode是一组字符设定(或者是从数字和字符之间的逻辑映射的概念编码)(注意非编码)
      而将这种映射的概念编码为数据的方式有很多: UCS-2(所有字符都占用两个), UCS-4(所有字符占用4个字节),UTF-16(大部分字符占用两个字节,有一些字符占用4个字节),UTF-8(用1-6个字节来编码字符)
    • 支持Unicode的程序中的正则表达式通常支持\u{unicode数字num}元序列,用来匹配一个具体的unicode字符;eg:\uC05B匹配的是编号为U+C05B的Unicode字符,而非具体的字节,因为具体的字节是由代表这个Unicode代码点的编码方式在内部决定的
    • 一般人眼里的字符并不都会被Unicode或者支持Unicode的程序(正则引擎)看作一个字符,比如é看上去是一个字符,其实在Unicode中它可能有两个代码点构成(一个表示e,一个表示钝重音) =>带来问题:点号(.)是匹配单个代码点还是整个代码点组合
    • 实践中,大部分程序将"字符"和"代码点"视为等价,及匹配单个代码点
    • 理论上Unicode应该是代码点和字符之间的一一映射,实际上存在多种情况,例如à可以表示为U+0061加上U+0300,它也可以用单个代码点U+00E0表示(原因是为了保证Unicode和Latin-1之间转换的简易性)
    • Unicode Version 3.1增加了U+FFFF之后的代码点(比如代表音乐谱号C的字符对应代码点U+1D121)
    • Unicode中的行终止符(存在多种)=>影响文本行从文件读入的方式,影响正则的点号(.)及^,$和\Z的匹配
    字符 Unicode码 描述
    LF U+000A ASCII换行符
    VT U+000B ASCII垂直制表符
    FF U+000C ASCII进纸符
    CR U+000D ASCII回车
    CR/LF U+000A U+000D ASCII回车/换行
    NEL U+0085 Unicode换行
    LS U+2028 Unicode行分隔符
    PS U+2029 Unicode段分隔符

    7.正则模式和匹配模式

    • 不区分大小写的匹配模式(i): 问题=>1.存在特殊的与Unicode相关的问题,即并非所有的ASCII字母和数字字符都存在大小写形式,某些字符在大写和小写之间没有明显的一对一映射
    • 宽松排列和注释模式: 此模式忽略字符组外部的所有空白字符
    • 点号通配模式(dot-match-all match mode,也叫单行模式):通常点号(.)无法匹配换行符,而大部分现代编程语言则提供了两种方法供正则表达式选择
    • 增强的行锚点模式(Enhanced Line-anchor match mode,也叫"多行文本模式"):影响行锚点"^"和""的匹配,通常情况下锚点"^"不能匹配字符串内部的换行符,而只能匹配目标字符串的起始位置,但是在此模式下能够匹配字符串内嵌的文本行的开头位置.支持此模式的程序通常提供"\A"和"\Z"元字符,作用于普通的"^"和""一样,只是在此模式下它们的意义不会发生变化,永远不会匹配字串内部的换行符
    • 文本文字模式: 此模式几乎不能识别任何正则表达式元字符(eg: [a-z]* 的正则在此模式下匹配的是字符串"[a-z]*")
    • “多行模式”和"单行模式"的区别: 后者修改的是点号的匹配规则(换行符需要特殊处理=>不需要特殊处理),前者修改的是"^"和"$"的匹配规则(换行符不需要特殊处理=>需要特殊处理)

    8.常见的元字符

    • 字符缩略表示法
    元字符 含义 解释
    \a 警报 对应ASCII中的<BEL>
    \b 退格 对应ASCII中的<BS>,八进制编码010,在许多流派中\b只有在字符组内才表示退格,否则代表单词边界
    \e Escape字符 通常对应ASCII中的<ESC>,八进制编码033
    \f 进纸符 对应ASCII中的<FF>,八进制编码014
    \n 换行符 macos平台中对应ASCII的<CR>,其他平台对应<LF>
    \r 回车 对应ASCII中的<CR>,MacOs中对应ASCII的<LF>
    \t 水平制表符 对应ASCII中的<HT>,八进制编码011
    \v 垂直制表符 对应ASCII中的<VT>,八进制编码013

    9.字符组及相关结构

    • 字符组通常表示肯定断言,即它必须匹配一个字符,排除型字符组仍然需要匹配一个字符,只是它没有在字符组中列出而已(注意[a-Z]和[a-zA-Z]的区别)
    • 点号能匹配除了换行符之外的任何字符(可以通过更改匹配模式切换)
    • Unicode属性,字母表和区块(p121,暂不记录)
    • .NET支持字符组减法(eg: [[a-z]-[aeiou]])

    10.锚点及其他"零长度断言"(只匹配位置)

    • 脱字符"^"匹配需要搜索的文本的起始位置,若使用了增强的行锚点匹配模式,还能匹配每个换行符之后的位置

    第4章

    1.正则引擎的分类

    • DFA 确定有限自动机DFA
    • NFA 不确定有限自动机

    相关文章

      网友评论

          本文标题:读《精通正则表达式》

          本文链接:https://www.haomeiwen.com/subject/znmfpqtx.html