正则表达式的基础

  正则表达式并不是Python的一部分。

  正则表达式是用于处理字符串的强大工具,拥有自己独特的语法以及一个独立的处理引擎,效率上可能不如str自带的方法,但功能十分强大。

  得益于这一点,在提供了正则表达式的语言里,正则表达式的语法都是一样的,区别只在于不同的编程语言实现支持的语法数量不同。

  就其本质而言,正则表达式(或 RE)是一种小型的、高度专业化的编程语言,(在Python中)它内嵌在Python中,并通过 re 模块实现。

元字符

元字符: . ^ $ * + ? { [ ] \ | ( )

. 匹配除了换行符外所有字符 (通配符)

  1. content = 'Abcdefghijklmnopq'
  2. test = re.findall(r"b.d",content)
  3. print(test)
  4. ['bcd']

^ 以....开头

  1. content = 'Abcdefghijklmnopq'
  2. test = re.findall(r"^Abcd",content)
  3. print(test)
  4. ['Abcd']

$ 以....结尾

  1. content = 'Abcdefghijklmnopq'
  2. test = re.findall(r"nopq$",content)
  3. print(test)
  4. ['nopq']

* 匹配0到多次 {0, }  控制它前面的字符

  1. content = 'Abcdefghijklmnopq'
  2. test = re.findall(r"A.*e",content)
  3. print(test)
  4. ['Abcde']

+ 匹配1到多次 {1, }

  1. content = 'abcdefab111111'
  2. test = re.findall(r"ab1+",content)
  3. print(test)
  4. ['ab111111']

?  匹配0到1次 {0,1}

  1. content = 'abcdefab111111'
  2. test = re.findall(r"ab1?",content)
  3. print(test)
  4. ['ab', 'ab1']

* +  都是按照贪婪模式进行匹配  非贪婪模式 需要在后面加个?

  1. content = 'abcdefab111111'
  2. test = re.findall(r"ab1+?",content)
  3. print(test)
  4. ['ab1']
  5.  
  6. re.search(r"a(\d+?)","a2345").group() => a2
  7.  
  8. re.search(r"a(\d*?)","a2345").group() => a
  9.  
  10. #如果前后均有限定条件 ?不起作用 re.search(r"a(\d*?)b","a2345b").group() => a2345b

( ) 组  作为一个整体

  1. content = 'abcdefab111111'
  2. test = re.findall(r"(ab1)",content)
  3. print(test)
  4. ['ab1']

{ }  重复次数自定义

  1. content = 'abcdefab111111'
  2. test = re.findall(r"ab1{3,9}",content)
  3. print(test)
  4. ['ab111111']

[ ]  字符集  表示或

      字符集里面元字符会失去意义   除了 -  \  ^ 3个元字符外

  1. content1 = 'wwwwwabdxxxxx'
  2. test1 = re.findall(r"a[bc]d",content1)
  3. print(test1)
  4. #['abd']
  5.  
  6. content2 = 'wwwwwacdxxxxx'
  7. test2 = re.findall(r"a[bc]d",content2)
  8. print(test2)
  9. #['acd']
  10.  
  11. ***********************************************************************
  12.  
  13. content = 'wwwwwa.xxxxx'
  14. test = re.findall(r"a[.]x",content)
  15. print(test)
  16. #['a.x']
  17.  
  18. content = 'wwwww1234xxxxx'
  19. test = re.findall(r"[1-9]",content) #1~9的数字
  20. print(test)
  21. #['1', '2', '3', '4']
  22.  
  23. content = 'wwwww1234xxxxx'
  24. test = re.findall(r"[^1-9]",content) #非1~9的数字
  25. print(test)
  26. #['w', 'w', 'w', 'w', 'w', 'x', 'x', 'x', 'x', 'x']

\ 作用:

  • 后面跟元字符去除特殊功能
  • 后面跟普通字符实现特殊功能
  • 引用序号对应的字组所匹配的字符串
  1. test = re.search(r"(alex)(eric)com\2","alexericcomeric")
  2. print(test.group())
  3. #alexericcomeric

\d  匹配任何十进制数, [0-9]

\D  匹配任何非数字字符 [^0-9]

\s   匹配任何空白字符 [ \t\n\r\f\v ]

\S  匹配任何非空白字符 [^ \t\n\r\f\v ]

\w  匹配任何字母数字字符 [a-zA-Z0-9_]

\W 匹配任何非字母数字字符 [^a-zA-Z0-9]

\b  匹配一个单词边界,单词和空格间的位置  匹配特殊字符(不单止空格)

  1. content = 'wwwww1234xxxxx'
  2. test = re.findall(r"\d",content)
  3. print(test)
  4. # ['1', '2', '3', '4']
  5.  
  6. content = 'ww&*#$%ww1234xx'
  7. test = re.findall(r"\D",content)
  8. print(test)
  9. # ['w', 'w', '&', '*', '#', '$', '%', 'w', 'w', 'x', 'x']
  10.  
  11. content = 'asdasd '
  12. test = re.findall(r"\s",content)
  13. print(test)
  14. # [' ', ' ', ' ']
  15.  
  16. content = ' asdasd '
  17. test = re.findall(r"\S",content)
  18. print(test)
  19. # ['a', 's', 'd', 'a', 's', 'd']
  20.  
  21. content = 'abc123^&*lm-\_'
  22. test = re.findall(r"\w",content)
  23. print(test)
  24. # ['a', 'b', 'c', '1', '2', '3', 'l', 'm', '_']
  25.  
  26. content = 'abc123^&*lm-\_'
  27. test = re.findall(r"\W",content)
  28. print(test)
  29. # ['^', '&', '*', '-', '\\']
  30.  
  31. content = 'I like Sooooo'
  32. test = re.findall(r"like\b",content)
  33. print(test)
  34. # ['like']
  35.  
  36. *******************************************
  37. test = re.findall(r"abc\b","asdasd abc ")
  38. test = re.findall(r"abc\b","asdasd abc*")
  39. print(test)
  40. # ['abc']

match()

  match()

  1. # match,从起始位置开始匹配,匹配成功返回一个对象,未匹配成功返回None
  2.  
  3. match(pattern, string, flags=0)
  4. # pattern: 正则模型
  5. # string : 要匹配的字符串
  6. # falgs : 匹配模式
  7.  
  8. # re.I(re.IGNORECASE): 忽略大小写(括号内是完整写法,下同)
  9. # M(MULTILINE): 多行模式,改变'^'和'$'的行为
  10. # S(DOTALL): 点任意匹配模式,改变'.'的行为 使 . 匹配包括换行在内的所有字符
  11. # L(LOCALE): 使预定字符类 \w \W \b \B \s \S 取决于当前区域设定
  12. # U(UNICODE): 使预定字符类 \w \W \b \B \s \S \d \D 取决于unicode定义的字符属性
  13. # X(VERBOSE): 详细模式。这个模式下正则表达式可以是多行,忽略空白字符,并可以加入注释。以下两个正则表达式是等价的:
  14.  
  15. *************************************
  16.  
  17. # match对象的方法
  18.  
  19. .group() 获取匹配到的所有结果
  20. .groups() 获取模型中匹配到的分组结果
  21. .groupdict() 获取模型中匹配到的分组中所有执行了key的组
  22. .group()    返回被RE匹配的字符串 可以加参数group(1) 组号
  23. .start() 返回匹配开始的位置
  24. .end()      返回匹配结束的位置
  25. .span() 返回一个元组包含的匹配的位置
  1. # 无分组
  2. r = re.match("h\w+", origin)
  3. print(r.group()) # 获取匹配到的所有结果
  4. print(r.groups()) # 获取模型中匹配到的分组结果
  5. print(r.groupdict()) # 获取模型中匹配到的分组结果
  6.  
  7. # 有分组
  8.  
  9. # 为何要有分组?提取匹配成功的指定内容(先匹配成功全部正则,再匹配成功的局部内容提取出来)
  10.  
  11. r = re.match("h(\w+).*(?P<name>\d)$", origin)
  12. print(r.group()) # 获取匹配到的所有结果
  13. print(r.groups()) # 获取模型中匹配到的分组结果
  14. print(r.groupdict()) # 获取模型中匹配到的分组中所有执行了key的组

demo

search()

  search()

  1. # search 匹配成功有结果,返回match对象
  2. # 查看返回结果用.group()
  3. # search,浏览整个字符串去匹配第一个,未匹配成功返回None
  4. # search(pattern, string, flags=0)
  1. # 无分组
  2.  
  3. r = re.search("a\w+", origin)
  4. print(r.group()) # 获取匹配到的所有结果
  5. print(r.groups()) # 获取模型中匹配到的分组结果
  6. print(r.groupdict()) # 获取模型中匹配到的分组结果
  7.  
  8. # 有分组
  9.  
  10. r = re.search("a(\w+).*(?P<name>\d)$", origin)
  11. print(r.group()) # 获取匹配到的所有结果
  12. print(r.groups()) # 获取模型中匹配到的分组结果
  13. print(r.groupdict()) # 获取模型中匹配到的分组中所有执行了key的组

demo

findall()

  findall()

  1. # 优先取组里内容返回!
  2. # findall,获取非重复的匹配列表;如果有一个组则以列表形式返回,且每一个匹配均是字符串;如果模型中有多个组,则以列表形式返回,且每一个匹配均是元祖;
  3. # 空的匹配也会包含在结果中
  4. # findall(pattern, string, flags=0)
  5.  
  6. data = re.findall("\d+\w\d+",'a2b3c4d5')
  7. # ['2b3', '4d5']
  8. # re.findall() 匹配成功一个后,从匹配成功最后位置开始下一次查找
  9.  
  10. # 空的匹配也会包含在结果中
  11. data = re.findall("",'a2')
  12. print(data)
  13. # ['', '', '']
  14.  
  15. ***********************************
  16.  
  17. #有几个括号就取几次
  18.  
  19. data = re.findall(r'(\dasd)*','1asd2asdp3asd3434')
  20. print(data)
  21. # ['2asd', '', '3asd', '', '', '', '', '']
  22. # 贪婪匹配 第一段取到1asd2asd 但最后返回 2asd 取最后一个!
  23.  
  24. 如下:
  25. a= "alex"
  26. data = re.findall(r'(\w)(\w)(\w)(\w)',a)
  27. print(data)
  28. # [('a', 'l', 'e', 'x')]
  29.  
  30. data = re.findall(r'(\w){4}',a)
  31. print(data)
  32. # ['x'] => 只是执行了4次,返回还是按一个括号算,取最后匹配的一项
  33.  
  34. ***********************************
  35.  
  36. test = re.findall("www.(baidu|laonanhai).com","asdsa www.baidu.com")
  37. print(test)
  38. # ['baidu']
  39.  
  40. 添加 ?: 去掉优先权
  41. test = re.findall("www.(?:baidu|laonanhai).com","asdsa www.baidu.com")
  42. print(test)
  43. # ['www.baidu.com']
  1. # 无分组
  2. r = re.findall("a\w+",origin)
  3. print(r)
  4.  
  5. # 有分组
  6. origin = "hello alex bcd abcd lge acd 19"
  7. r = re.findall("a((\w*)c)(d)", origin)
  8. print(r)
  9. # [('bc', 'b', 'd'), ('c', '', 'd')]

demo

sub()

  sub()

  1. # sub,替换匹配成功的指定位置字符串
  2.  
  3. sub(pattern, repl, string, count=0, flags=0)
  4. # pattern: 正则模型
  5. # repl : 要替换的字符串或可执行对象
  6. # string : 要匹配的字符串
  7. # count : 指定匹配个数
  8. # flags : 匹配模式
  9.  
  10. test = re.sub("g.t","have","I get A, I got B , I gut C")
  11. print(test)
  12. #I have A, I have B , I have C
  13.  
  14. ********************************************
  15.  
  16. #subn 最后还返回一个替换次数
  17.  
  18. origin = "ale4 xc 19"
  19. data,counts = re.subn("\d+","KKK",origin)
  20. print(data,counts)
  21. # aleKKK xc KKK 2

compile()

  compile()

  1. regex = re.compile(r"\w*oo\w*")
  2. text = " JGood is ,he is cool"
  3. data = regex.findall(text)
  4. print(data)
  5. #['JGood', 'cool']

split()

  split()

  1. # split,根据正则匹配分割字符串
  2. split(pattern, string, maxsplit=0, flags=0)
  3.  
  4. # pattern: 正则模型
  5. # string : 要匹配的字符串
  6. # maxsplit:指定分割个数
  7. # flags : 匹配模式
  8.  
  9. *****************************************
  10. # 有分组情况下, 把分割的项也添加进去
  11.  
  12. origin = "hello alex bcd alex lge alex acd 19"
  13. r1 = re.split("(alex)", origin, 1)
  14. print(r1)
  15. # ['hello ', 'alex', ' bcd alex lge alex acd 19']
  16.  
  17. r2 = re.split("(al(ex))", origin, 1)
  18. print(r2)
  19. # ['hello ', 'alex', 'ex', ' bcd alex lge alex acd 19']
  20.  
  21. *****************************************
  22.  
  23. p = re.compile(r"\d+")
  24. test = p.split("one1two2three3four4")
  25. print(test)
  26. # ['one', 'two', 'three', 'four', '']
  27. # 末尾有空字符串
  28.  
  29. => one,two2three3four4 => ['one'] two,three3four4 => ..
  30.  
  31. test = re.split('[bc]','abcd')
  32. print(test)
  33. # ['a', '', 'd']
  1. # 无分组
  2. origin = "hello alex bcd alex lge alex acd 19"
  3. r = re.split("alex", origin, 1)
  4. print(r)
  5.  
  6. # 有分组
  7.  
  8. origin = "hello alex bcd alex lge alex acd 19"
  9. r1 = re.split("(alex)", origin, 1)
  10. print(r1)
  11. r2 = re.split("(al(ex))", origin, 1)
  12. print(r2)

demo

finditer()

  finditer()

  1. # 返回结果为迭代对象
  2.  
  3. p = re.compile(r"\d+")
  4. w = p.finditer(' 1 drum44ers druming , 11 ... 10 ...')
  5. for match in w:
  6. print(match.group(),match.span())
  7.  
  8. # 1 (1, 2)
  9. # 44 (7, 9)
  10. # 11 (23, 25)
  11. # 10 (30, 32)

反斜杠的困扰

与大多数编程语言相同,正则表达式里使用"\"作为转义字符,这就可能造成反斜杠困扰。

假如你需要匹配文本中的字符"\",那么使用编程语言表示的正则表达式里将需要4个反斜杠"\\\\"

前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。

Python里的原生字符串很好地解决了这个问题,这个例子中的正则表达式可以使用r"\\"表示。

同样,匹配一个数字的"\\d"可以写成r"\d"。有了原生字符串,你再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。

常用正则表达式

  1. # IP:
  2. ^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$
  3.  
  4. # 手机号:
  5. ^1[3|4|5|8][0-9]\d{8}$
  6.  
  7. # 邮箱:
  8. [a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+

练习题:计算器

  1. #!/usr/bin/env python
  2. # -*-coding:utf-8 -*-
  3.  
  4. import re
  5.  
  6. # 加减运算:
  7. def add_sub(origin):
  8. '''
  9. 进行加减运算,按+ - 符号拆分,
  10. :param origin: 传入的表达式
  11. :return:
  12. '''
  13. data = re.split('([+-]{1})', origin)
  14. # 预处理 把 '' 转换成 '0'
  15. for i in range(len(data)):
  16. if data[i].strip() == '':
  17. data[i] = ''
  18. # 预处理 负负得正 情况:
  19. for i in range(len(data)):
  20. if data[i].strip() == '' and i != 0 :
  21. if data[i-1].strip() == '-':
  22. data[i+1] = '+'
  23.  
  24. # 计算开始:
  25. total = 0
  26. # flag = 0 默认加号 1为减号
  27. flag = 0
  28. for i in range(len(data)):
  29. if data[i].strip() == '-':
  30. flag = 1
  31. continue
  32. elif data[i].strip() == '+':
  33. flag = 0
  34. continue
  35. elif flag == 0 :
  36. total += float(data[i].strip()) if '.'in data[i] else int(data[i].strip())
  37. elif flag == 1 :
  38. total -= float(data[i].strip()) if '.'in data[i] else int(data[i].strip())
  39.  
  40. return total
  41.  
  42. # 计算乘除,乘方运算:
  43. def plus_div(origin):
  44. '''
  45. 按前后顺序拆分,需要进行 乘除,乘方 运算的地方,获得式子,计算出结果,顶替回原来位置,循环此步骤,只剩加减法,再把只剩加减法的式子传入add_sub()计算
  46. :param origin: 传入的表达式
  47. :return:
  48. '''
  49. while True:
  50. data = re.split('([-]?\d+\.?\d*\s*(?:[*/]|\*\*)\s*[-]?\d+\.?\d*)',origin,1)
  51. # 判断表达式是否只剩加减运算 , 传入 add_sub() 进行加减法的计算
  52. if len(data) ==1:
  53. result = add_sub(data[0])
  54. return result
  55. break
  56. # 判断表达式是否还包含 乘除,乘方 符号 ,如果包含,继续拆分运算,最终获得只剩加减的式子
  57. elif len(data) ==3:
  58. counts = data[1] # 获得匹配出的 运算符号 * / 或 **
  59. before, content, after = data
  60. else:
  61. print('Error')
  62.  
  63. # 判断需要进行哪种运算,
  64. if '**' in counts:
  65. num = counts.split('**')
  66. left = float(num[0].strip()) if '.'in num[0] else int(num[0].strip())
  67. right = float(num[1].strip()) if '.' in num[1] else int(num[1].strip())
  68. total = left ** right
  69.  
  70. elif '/' in counts:
  71. num = counts.split('/')
  72. left = float(num[0].strip()) if '.'in num[0] else int(num[0].strip())
  73. right = float(num[1].strip()) if '.' in num[1] else int(num[1].strip())
  74. total = left / right
  75.  
  76. elif '*' in counts:
  77. num = counts.split('*')
  78. left = float(num[0].strip()) if '.'in num[0] else int(num[0].strip())
  79. right = float(num[1].strip()) if '.' in num[1] else int(num[1].strip())
  80. total = left * right
  81.  
  82. # 此时只进行了表达式内的一次乘除,乘方运算, 计算结果拼接顶替原来的位置,继续循环直到只剩加减法
  83. origin = before + str(total) + after
  84.  
  85. def count(origin):
  86. """
  87. 1.一步一步拆分括号,每获得一次 最里层的括号表达式 ,就传入plus_div()函数 进行 该表达式的所有乘除运算,再进行加减运算,返回该表达式最终结果,
  88. 拼接回原表达式,替换回括号位置.再循环寻找下一个括号内表达式,直到所有括号的表达式计算完毕,最终只剩一条只包含单纯的乘除加减运算的表达式.
  89.  
  90. :param origin: 需要计算的表达式
  91. :return:
  92. """
  93. while True:
  94. # 拆分() 获得最里层的括号!
  95. data = re.split('\(([^()]+)\)',origin,1)
  96. if len(data) == 3:
  97. before,content,after = data
  98. result = plus_div(content) # () 里面的表达式传入 plus_div 进行计算
  99. origin = before + str(result) + after # 把计算结果 拼接回原来括号的位置. 进行下一次括号寻找!
  100. else:
  101. # 当只剩一条只包含单纯的乘除加减运算的表达式时,
  102. result = plus_div(data[0])
  103. return result
  104. break
  105.  
  106. origin = " 6 * 2 + ( 4 -3.5 + 1 * 91 + (-1 +2) * 5 -5 ) / 2 + 2 ** 9"
  107. result = count(origin)
  108.  
  109. print('表达式: ' + origin)
  110. print('我的计算结果 :\n' + str(result))
  111. print('eval计算结果: \n'+ str(eval(origin)))

【Python之路】特别篇--Python正则表达式的更多相关文章

  1. Python之路(第九篇)Python文件操作

    一.文件的操作 文件句柄 = open('文件路径+文件名', '模式') 例子 f = open("test.txt","r",encoding = “utf ...

  2. 【Python之路】特别篇--Python面向对象(进阶篇)

    上一篇<Python 面向对象(初级篇)>文章介绍了面向对象基本知识: 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 是一个模板,模板中包装了多个“函数”供使 ...

  3. 【Python之路】特别篇--Python面向对象(初级篇)

    概述 面向过程:根据业务逻辑从上到下写垒代码 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象:对函数进行分类和封装,让开发“更快更好更强...” 面向过程编程最易被初学 ...

  4. python之路基础篇

    基础篇 1.Python基础之初识python 2.Python数据类型之字符串 3.Python数据类型之列表 4.Python数据类型之元祖 5.Python数据类型之字典 6.Python Se ...

  5. python之路入门篇

    一. Python介绍 python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,Guido开始写能够解释Python语言语法的解释器.Python这个名字,来 ...

  6. python之路第一篇

    一.python环境的搭建 1.window下环境的搭建 (1).在 https://www.python.org/downloads/ 下载自己系统所需要的python版本 (2).安装python ...

  7. python之路第二篇(基础篇)

    入门知识: 一.关于作用域: 对于变量的作用域,执行声明并在内存中存在,该变量就可以在下面的代码中使用. if 10 == 10: name = 'allen' print name 以下结论对吗? ...

  8. 【python之路1】python安装与环境变量配置

    直接搜索 Python,进入官网,找到下载,根据个人电脑操作系统下载相应的软件.小编的是windows os .下载python-2.7.9.msi 安装包  双击安装程序,进入安装步骤.在安装过程中 ...

  9. 【Python之路】特别篇--Python切片

    字符串切片操作 切片操作符是序列名后跟一个方括号,方括号中有一对可选的数字,并用冒号分割. 注意: 数是可选的,而冒号是必须的. consequence[start:end:step] 切片操作符中的 ...

随机推荐

  1. php exec执行不等待返回结果

    windows中:pclose(popen("start php.exe test.php","r"));lnuix中: pclose(popen(" ...

  2. python中的类变量和对象变量,以及传值传引用的探究

    http://www.cnblogs.com/gtarcoder/p/5005897.html http://www.cnblogs.com/mexh/p/9967811.html

  3. Jmeter安装及配置(含JDK安装)

    (一)java环境配置1.官网下载64位的jdkhttp://www.oracle.com/technetwork/java/javase/downloads/index.html 2.环境变量设置变 ...

  4. Java Web ActiveMQ与WebService的异同

    Webservice 和MQ(MessageQueue)都是解决跨平台通信的常用手段 一.WebService:用来远程调用服务,达到打通系统.服务复用的目的.是SOA系统架构——面向服务架构的体现. ...

  5. sql lesson21homework

    2017-08-15 18:03:17 mysql> show databases;+--------------------+| Database           |+---------- ...

  6. C# 常用类库说明

    Array类 用括号声明数组是C#中使用Array类的记号.在后台使用C#语法,会创建一个派生于抽象基类Array的新类.这样,就可以使用Array类为每个C#数组定义的方法和属性了. Array类实 ...

  7. shell、bash、terminal和kernel之间的关系

    shell.bash.terminal和kernel之间的关系 本文是<鸟哥的Linux私房菜>的学习笔记 什么是kernel kernel的中文是"操作系统核心",主 ...

  8. Windows Class Styles

    CS_VREDRAW:当窗口水平方向的宽度变化时重绘整个窗口 CS_HREDRAW:当窗口垂直方向的宽度变化时重绘整个窗口 CS_DBLCLKS:指针在属于此类的窗体内部,并且用户双击时,收到一个双击 ...

  9. 查询SQL Server版本号

    一.查看SQL Server 2005版本号 SELECT @@VERSION 显示以下信息: Microsoft SQL Server 2005 - 9.00.3042.00 (Intel X86) ...

  10. vue事件处理机制

    <button @click="handleAdd1()">add1</button> <button @click="handleAdd2 ...