Python——正则表达式


将文本分行

  • text.split("\n")
    • 适用于普通文本,这种文本的特点是写到文件或者print输出后看不到\n字符串,自动转义成换行符,显示出来就是分行的
  • text.split("\\n")
    • 适用于被编码后的文本,该文本的特点是经过编码,所以写到文件或者输出时还能看到\n字符串,本质上需要二次转义才能显示为换行符号
  • text.split(r"\n")
    • 同上,等价与告诉别人不需要转义r"\n"本身代表着"\n"是原始文本,无需转义,体现在分
  • text.decode("unicode-escape").split("\n")
    • 效果同上
  • 第一种文本是一次转义就能按行显示的文本,比如一次print和write操作都会转义
  • 后三种文本需要两次转义才能按行显示,中间两种分割方式等价,最后一种是先转义再分割

正则表达式匹配完整字符串

  • 必须使用^和$, 否则部分匹配也会返回结果
    1
    2
    3
    4
    5
    import re
    def totally_match(pattern, string):
    if re.match(pattern, string) is not None:
    return True
    totally_match(r"^cat$", "cat")

正则表达式替换指定范式的字符

  • 要求:替换问题[数字1]:[数字2]公式[数字1]。[数字2],即其中问题:替换为公式,并保留[数字]部分
    • 比如:替换问题1:100公式1。100
  • 实现方式:
    1
    2
    3
    4
    5
    import re
    text = "问题1:100 这是一个示例"
    # r'问题(\d+):(\d+)',(\d+) 是两个捕获组,分别用于捕获数字1和数字2,替换为:r'公式\1。\2',解释:\1 表示第一个捕获组的内容(数字1),\2 表示第二个捕获组的内容(数字2)
    result = re.sub(r'问题(\d+):(\d+)', r'公式\1。\2', text)
    print(result)

附录:高阶正则表达式

  • 整体来说,比较常用的正则表达式如下:
    语法 名称 功能
    (?=...) 正向前瞻 后面必须是指定的模式
    (?!...) 负向前瞻 后面不能是指定的模式
    (?<=...) 正向后瞻 前面必须是指定的模式
    (?<!...) 负向后瞻 前面不能是指定的模式
    (?:...) 非捕获组 组合但不捕获
    (?P<name>...) 命名捕获组 捕获并命名
    (?>...) 原子组 匹配后不回溯
    (?(...)...) 条件匹配 根据条件匹配不同模式
  • 其中(?...)是一种特殊的模式,其他字符表示如下:
    • =表示匹配(对应为正),相反的是!表示不匹配(对应为负)
    • <表示向后匹配,向后看(后瞻),相反的是不使用<,则表示向前看(前瞻)

正向前瞻(Positive Lookahead)

  • 语法(?=...)
  • 功能 :匹配某个位置,要求该位置后面必须是指定的模式
  • 示例
    • 正则表达式:\d(?=px)
    • 匹配:数字后面必须是 px,但只匹配数字
    • 输入:10px 20em
    • 匹配结果:1(在 10px 中),2(在 20em 中不匹配,因为后面是 em

负向前瞻(Negative Lookahead)

  • 语法(?!...)
  • 功能 :匹配某个位置,要求该位置后面不能是指定的模式
  • 示例
    • 正则表达式:\d(?!px)
    • 匹配:数字后面不能是 px,但只匹配数字
    • 输入:10px 20em
    • 匹配结果:0(在 10px 中不匹配,因为后面是 px),2(在 20em 中)

正向后瞻(Positive Lookbehind)

  • 语法(?<=...)
  • 功能 :匹配某个位置,要求该位置前面必须是指定的模式
  • 示例
    • 正则表达式:(?<=\$)\d+
    • 匹配:前面是 $ 的数字
    • 输入:$100 €200
    • 匹配结果:100$100 中的数字),200 不匹配,因为前面是

负向后瞻(Negative Lookbehind)

  • 语法(?<!...)
  • 功能 :匹配某个位置,要求该位置前面不能是指定的模式
  • 示例
    • 正则表达式:(?<!\$)\d+
    • 匹配:前面不是 $ 的数字
    • 输入:$100 200
    • 匹配结果:200$100 中的 100 不匹配,因为前面是 $

非捕获组(Non-capturing Group)

  • 语法(?:...)
  • 功能 :匹配部分符合预期的字符,但不捕获匹配的内容(即不会生成反向引用)
  • 示例
    • 正则表达式:(?:https?://)(\w+)
    • 匹配:http://https:// 后面的单词,但只捕获单词部分
    • 输入:http://example.com https://test.com
    • 匹配结果:exampletest

命名捕获组(Named Capturing Group)

  • 语法(?P<name>...)
  • 功能 :将匹配的内容捕获到一个命名组中,可以通过名称引用
  • 示例
    • 正则表达式:(?P<year>\d{4})-(?P<month>\d{2})
    • 匹配:日期中的年份和月份,并分别命名为 yearmonth
    • 输入:2023-10
    • 匹配结果:year=2023month=10

原子组(Atomic Group)

  • 语法(?>...)
  • 功能 :将组内的匹配作为一个原子操作,一旦匹配成功,就不会回溯
  • 示例
    • 正则表达式:(?>a+)ab
    • 匹配:一个或多个 a,后面必须是 ab,且不会回溯
    • 输入:aaab
    • 匹配结果:无匹配,因为(?>a+)先匹配了aaa,导致正则表达式的ab无法与b匹配,此时不再回溯
    • 注:作为对照,正则表达式 a+ab可以匹配aaab,因为a+先匹配了aaa,正则表达式的ab无法与b匹配,此时会回溯到a+先匹配了aa,正则表达式的abab匹配

条件匹配(Conditional Matching)

  • 语法(?(condition)true-pattern|false-pattern)
  • 功能 :根据条件匹配不同的模式
  • 示例
    • 正则表达式:(?(?<=foo)bar|baz)
    • 匹配:如果前面是 foo,则匹配 bar,否则匹配 baz
    • 输入:foobar testbaz
    • 匹配结果:bar(在 foobar 中),baz(在 testbaz 中)。