《正则指引》学习笔记

2024年03月05日 阅读915次 分类:笔记 标签:js

版权声明:本文为博主原创或转载自网络,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:http://zhuyanjun.cn/note/1934.html

书本《正则指引》,示例语言python

一、字符

  1. [...]的形式指字符组,用于匹配指定字符。
  2. [x-y]的形式指范围表示法,例:[0-9]表示[0123456789]
  • 范围的本质是字符在ASCII中的码值从小到大的排序
  • 可以并列多个范围表示法,例:[0-9a-zA-Z]
  • 字符可以用\xhex的形式表示(可以匹配中文字符),\x固定值,hex指字符对应码值,例:\x41表示字母A
  • 元字符指用于特殊含义的字符,例:[]-^$等等。
    • 字符-如果紧邻[[^表示字符,其他情况是元字符,例:[-09]表示“-09”三个字符,而非“0123456789”十个字符
    • \可以转义元字符为普通字符,但写在""引号之间时要用\\,例:只匹配有3个字符的字符串0-9,需要这样写regStr = "[0\\-9]"
  • [^...]的形式指排除当前范围。
  • 字符组简记法\d\w\s\D\W\S
    • \d[0-9]匹配数字
    • \w[0-9a-zA-Z_]匹配单词
    • \s[ \t\r\n\v\f](第一个是空格)匹配空白字符
    • 大写\D\W\S指上面三个的排除
    • . 匹配除\n之外的任何单个字符
    • 可以使用[\s\S][\d\D][\w\W]来匹配任意字符
  • 字符运算(java和.net支持),例:26个字母中排除“aeiou”几个字母。
    • java中[[a-z]&&[^aeiou]]
    • .net中[a-z-[aeiou]]
  • POSIX字符组,属于另一种正则流派,形式类似:[:digit:][:lower:]
  • 二、量词

    1. 量词的基本形式
    • {m,n} 之前的元素最少出现m次,最多出现n
    • {n} 之前的元素必须出现n
    • {m,} 之前的元素必须出现m次,最多无上限
    • {0,n} 之前的元素可以出现或不出现,最多出现n
  • 其他常用量词
    • + 等价于{1,}
    • ? 等价于{0,1}
    • * 等价于{0,}
  • 转义
    • 基本量词形式字符串在开头加\即可,例:要匹配字符串“{m,n}”必须写成\{m,n}
    • 其他常用量词形式直接加\即可,例:\+\?\*

    三、括号

    1. (...)形式叫做分组
    2. (...|...)形式叫做多选分支,可以分割多个子表达式,数目无限制。
    • 多选结构也可以没有()括号(不推荐),例:ab|cd等价于(ab|cd)
    • 多选结构每个分支必须明确写出,不能使用-范围法
  • 引用分组指使用()括号后,正则表达式会保存每个分组匹配的文本,待匹配完成后返回。
    • 可以使用group(num)方法获取,num指分组编号
    • 规则是:从左向右按照开括号出现的顺序计数
    • 1开始,编号为0的分组是默认存在的
  • 反向引用指在表达式内部使用\num。例:检测字符串“deep”是否含有叠词,表达式为([a-z])\1,其中[a-z]匹配第一个字母\1表示反向引用之前匹配的字母。
  • 可以用于数据替换,re.sub(pattern,replacement,string)其中replacement待替换字符可以引用分组,形式是\numnum是分组编号,\num在字符串中是非合法转义序列,所以非原生字符串需\\num才有效)。例:替换字符串“2023-03-23”为“2023年3月23日”,表达式为re.sub(r"(\d{4})-(\d{2})-(\d{2})",r"\1年\2月\3日","2023-03-23")
  • 各语言中的反向引用的差异
    • .net:表达式中\num,替换的字符串中$num
    • java:表达式中\num,替换的字符串中$num
    • js:表达式中$num,替换的字符串中$num
    • php:表达式中\num,替换的字符串中$num或\num
    • python:表达式中\num,替换的字符串中\num
    • ruby:表达式中\num,替换的字符串中\num
  • 反向引用的2义性,指匹配分组超过10个时,反向引用10以上的数字时\10中的0会出现两种意义(匹配规则默认是第10个分组,但我只想引用第1个,后面这个0是独立的)。精确标注:
    • python中使用\g<1>0
    • php中使用\${1}0
    • 其他语言会自动判断,但也无解,引用分组不要超过9个就行
  • 命名分组用于解决\num数字不直观和2义性,各语言差异
    • .net:分组(?<name>...),表达式中\k<name>,替换的字符串中${name}
    • java7+:分组(?<name>...),表达式中\k<name>,替换的字符串中${name}
    • js:不支持
    • php:分组(?P<name>...),表达式中(?P=name),替换的字符串中不支持
    • python:分组(?P<name>...),表达式中(?P=name),替换的字符串中\g<name>
    • ruby:分组(?<name>...),表达式中\k<name>,替换的字符串中\k<name>
  • 非捕获分组(?:...),匹配但捕获,可以提高运行时性能。
  • 其他
    • apachenginx的替换规则为$num
    • iis的替换规则为{R:num}

    三、断言

    不真正匹配文本,而只负责判断在某个位置左/右侧的文本是否符合要求,这种结构被称为断言。

    1. \b用于匹配单词边界,也就是指单词和空格间的位置
    2. 行起始/结束位置
    • ^用于匹配行的开头位置,例:字符串“first line\nsecond line\r\nlast line”,多行模式下,行开头可以匹配到3个
    • \A(js不支持)用于匹配整个字符串开头,不管有没有行。
    • $用于匹配行的结束位置,包含\n换行符的情况
    • \z(python是\Z,js不支持)用于匹配行的结束位置,不包含\n换行符的情况
    • ^$进行正则表达式替换时并不会被替换,只会在起始/结束位置添加一些字符,位置本身仍然存在
  • 环视指在某个位置向左/向右看,必须出现或不能出现某类字符
    • (?!...)当前位置之后不允许出现某个字符,例:A(?!abc)指字母A后不能出现字符串abc
    • (?<!...)当前位置之前不允许出现某个字符
    • (?=...)当前位置之后必须出现某个字符
    • (?<=...)当前位置之前必须出现某个字符

    四、匹配模式

    1. (?模式1模式N)用于指定匹配模式,js除外。如果写在表达式中表示从当前位置开始
    • (?i)用于指定匹配小写,例如:re.search(r"(?i)the","The")
    • (?s)用于匹配单行模式,行指换行符
    • (?m)用于匹配多行模式
    • (?x)用于注释模式,可以在表达式内部夸多行对表达式进行解释。(?#...)这种形式注释在java和js中无效
  • (?-模式1模式N)用于结束匹配模式
  • 如果匹配模式写在((?模式)...)...中,则作用范围就在括号内(python不支持)
  • 五、其他

    1. 表达式优先级
      1. ()
      2. * ? +
      3. abc
      4. a|b
    2. 各语言匹配的默认编码
    • NE、Python 3T默认采用Unicode匹配规则,但可以显式指定采用ASCII匹配规则
    • Java、js、php 默认采用ASCII匹配规则
  • 常用匹配汉字
    • [\u4e00-\u9fa5]可以仅匹配中文
    • [^\x00-\xff]匹配所有全角符号,包含汉字和全角标点
  • 尽量不要使用以下表达式
    • .*(…*)*虽然可以匹配但回朔多,造成慢和损耗性能

    (本篇完)

    是不是学到了很多?可以

    版权声明:本文为博主原创或转载自网络,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

    本文链接:http://zhuyanjun.cn/note/1934.html