正则表达式和re模块

正则表达式

  • 本身也和python没有什么关系,就是匹配字符串内容的一种规则。
  • 正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑
元字符

. 匹配除换行符以外的任意字符
\w 匹配字母或数字或下划线
\s 匹配任意的空白符
\d 匹配数字
\n 匹配一个换行符
\t 匹配一个制表符
\b 匹配一个单词的结尾
^ 匹配字符串的开始
$ 匹配字符串的结尾
\W 匹配非字母或数字或下划线
\D 匹配非数字
\S 匹配非空白符
a|b 匹配字符a或字符b 左边|右边
() 匹配括号内的表达式,也表示一个组
[...] 匹配字符组中的字符
[^...] 匹配除了字符组中字符的所有字符

量词

*重复零次或更多次
+重复一次或更多次
? 重复零次或一次
{n} 重复n次
{n,} 重复n次或更多次
{n,m} 重复n到m次

两次后面加上?就是惰性匹配
不加就是贪婪匹配

  • 就是取前面任意长度的字符,直到一个x出现
.*?x 
  • findall
import re

ret = re.findall('a', 'eva egon yuan')  # 返回所有满足匹配条件的结果,放在列表里
print(ret) # ['a', 'a']

# findall 有一个特点,会优先显示分组中的内容   (?:)取消分组优先
# 多个分组会以[('www', 'baidu', 'com')]形式返回 
ret = re.findall('\d(\.\d)?[*/]\d','1.5*5')
print(ret)  # ['.5']    

ret = re.findall('\d+\.\d+|\d+',"1-2*(60+(-40.35/5)-(-4*3))")
print(ret)

ret = re.findall('(\d+\.\d+|\d+)',"1-2*(60+(-40.35/5)-(-4*3))")
print(ret)   # 同上
  • search
ret = re.search('\d+','SGahsf')
print(ret)
if ret:
    print(ret.group())
search
返回值 : 返回一个SRE_Match对象
          通过group去取值
          且只包含第一个匹配到的值
          
ret = re.search('(www)\.(baidu|oldboy)\.(com)', 'www.baidu.com')
print(ret.group(0))    
print(ret.group(1))   #第一组   显示分组优先
print(ret.group(2))    #第二组
print(ret.group(3))       #第三组  
  • 算式中匹配出最内层小括号以及小括号内的表达式
\([^()]+\)
  • 匹配出从左到右第一个乘法或除法
#-?\d+(\.\d+)?[*/]-?\d+(\.\d+)?
ret = re.search('-?\d+(\.\d+)?[*/]-?\d+(\.\d+)?','9.0-2.22*5/3+7/3*99/4*2998+10*568/14')
print(ret.group())
# \d+(\.\d+)?[*/]-?\d+(\.\d+)?
ret = re.search('\d+(\.\d+)?[*/]-?\d+(\.\d+)?','9.0-2.22*5/3+7/3*99/4*2998+10*568/14')
print(ret.group())
  • 乘除法
exp  = '2*3/4*5'
import re
def mul_div(son_exp):
    if '*' in son_exp:
        a, b = son_exp.split('*')
        mul = float(a) * float(b) # 6
        return mul
    elif '/' in son_exp:
        a, b = son_exp.split('/')
        div = float(a) / float(b)  # 6
        return div  

while True:
    ret = re.search('-?\d+(\.\d+)?[*/]-?\d+(\.\d+)?',exp)
    if ret:
        son_exp = ret.group()   # '2*3'
        res = mul_div(son_exp)
        exp = exp.replace(son_exp,str(res))
    else:break
print(exp,type(exp))
  • match(search) 验证用户输入内容 -->默认从头开始匹配,和search类似
ret = re.match('\d+','293ahs293djjk293sahf2938u')   
#search  中在正则表达式中加'^'
print(ret)  
#<_sre.SRE_Match object; span=(0, 3), match='293'>   ..span=(0, 3)-->索引
print(ret.group())
  • 切割split 有分组优先
s1 = 'alex||egon|boss_jin'
print(s1.split('|'))

s = 'alex8123egon1120boss_jin'
ret = re.split('\d+',s)
print(ret)  # ['alex', 'egon', 'boss_jin']
ret = re.split('(\d+)',s)  # (\d)+  相当于\d\d\d\d\d...(\d)
print(ret)  # ['alex', '8123', 'egon', '1120', 'boss_jin']
ret = re.split('\d(\d)',s)
print(ret)  # ['alex', '1', '', '3', 'egon', '1', '', '0', 'boss_jin']
  • 替换sub(replace)
s = 'alex|egon|boss_jin'
print(s.replace('|','-'))

s1 = 'alex8123egon1120boss_jin626356'
ret = re.sub('\d+','|',s1)
print(ret)
ret = re.sub('\d+','|',s1,1)
print(ret)
ret = re.subn('\d+','|',s1)   # 统计替换了多少次
print(ret)
  • compile 编译正则规则
    • 将正则表达式编译成为一个 正则表达式对象
      再次使用的是否不用再编译,执行速度相对快
com = re.compile('\d+')
print(com)
ret = com.search('abc1cde2fgh3skhfk')
print(ret.group())
ret = com.findall('abc1cde2fgh3skhfk')
print(ret)
ret = com.finditer('abc1cde2fgh3skhfk')
for i in ret:
    print(i.group())
  • finditer 节省空间的方法
ret = re.finditer('\d+','abc1cde2fgh3skhfk')
print(ret) 
for i in ret:
    print(i.group())
    
ret = re.finditer('\d', 'ds3sy4784a')   
#finditer返回一个存放匹配结果的迭代器
print(ret)  # 
print(next(ret).group())  #查看第一个结果
print(next(ret).group())  #查看第二个结果
print([i.group() for i in ret])  #查看剩余的左右结果
  • 前端
    • 分组命名
    • 分组约束
    • 实际上对于前端语言来说 都是把不同样式的字体放在不同的标签中--->标签语言

函数

函数 <(.*?)>.*? #分组约束
pattern = '<(?P.*?)>.*?'
ret = re.search(pattern,'

函数

') print(ret) if ret: print(ret.group()) print(ret.group(1)) print(ret.group('tag')) pattern = r'<(.*?)>.*?' ret = re.search(pattern,'函数') print(ret) if ret: print(ret.group()) print(ret.group(1))

(?:正则表达式) 表示取消优先显示功能
(?P<组名>正则表达式) 表示给这个组起一个名字
(?P=组名) 表示引用之前组的名字,引用部分匹配到的内容必须和之前那个组中的内容一模一样

re模块: findall search finditer compile

异常处理

  • 异常错误和语法错误不同:

    • 异常错误编译阶段没问题执行时发生错误(逻辑错误)
      • 即便是放在try语句中的内容,在遇到报错之后也会中断这段语句的执行
    • 语法错误编译阶段就就过不去
    • PyCharm多行内容报错-->排错从下往上看
      [图片上传失败...(image-287b2a-1537186793503)]
  • 如果错误发生的条件是可预知的,我们需要用if进行处理:在错误发生之前进行预防

  • 如果错误发生的条件是不可预知的,则需要用到try...except:在错误发生之后进行处理

  • as语法
    这个e是异常类的一个实例,如果我们完整地解释这个问题,我觉得还是从Python的自定义异常类说起比较好。

假如,我们现在自定义一个简单的异常类:

class MyError(Exception):
    def __init__(self, value):
        self.value = value
    def __str__(self):
        return repr(self.value)

我们抛这个异常的时候可以这么写:

try:
    raise MyError(2*2)
except MyError as e:
    print 'My exception occurred, value:', e.value

我们在捕获这个异常之后假如需要访问TA的一些属性怎么办,这个时候就可以使用as关键字
所以,这里的e是前面MyError类的一个instance,我们可以直接访问他的value,也就是你看到的e.value

  • 单分支
#基本语法为
try:
    被检测的代码块
except 异常类型:
    try中一旦检测到异常,就执行这个位置的逻辑

  • 万能异常
# 万能异常Exception
s1 = 'hello'
try:
    int(s1)
except Exception as e:
    print(e)

  • 多分支 --> 也可以在多分支后来一个Exception
s1 = 'hello'
try:
    int(s1)
except IndexError as e:
    print(e)
except KeyError as e:
    print(e)
except ValueError as e:
    print(e)

  • 合并多分支
try:
    num = int(input('num : '))
    print(l[num - 1])
except (ValueError,IndexError):
    print('输入了错误的内容')
  • 多分支异常与万能异常

    • 如果你想要的效果是,无论出现什么异常,我们统一丢弃,或者使用同一段代码逻辑去处理他们,那么骚年,大胆的去做吧,只有一个Exception就足够了。
    • 如果你想要的效果是,对于不同的异常我们需要定制不同的处理逻辑,那就需要用到多分支了。
  • else

    • 汇报这段代码顺利的执行了 : 发短信通知,记录到文件中
    • try/except/else
  • finally

    • try/finally
    • try/ except / finally
    • try/ except / else / finally
s1 = 'hello'
try:
    int(s1)
except IndexError as e:
    print(e)
except KeyError as e:
    print(e)
except ValueError as e:
    print(e)
except Exception as e:
    print(e)
else:
    print('try内代码块没有异常则执行我')
finally:
    print('无论异常与否,都会执行该模块,通常是进行清理工作')

try/except
try/except/else
try/finally
try/ except / finally
try/ except / else / finally

  • 自定义异常
class EvaException(BaseException):  #BaseException 相当于类的object
    def __init__(self,msg):
        super().__init__()
        self.msg = msg
    def __str__(self):
        return self.msg

raise EvaException('eva的异常')
  • raise 主动触发异常,抛出/引发异常 (写框架写程序员用到)
  • assert 断言:assert 条件 (写框架写程序员用到
assert 1 == 1   #条件为真执行
print('*'*100)
assert 1 == 2  #条件为假,报错
print('*'*100)
  • assert 简化了raise语句:
    需要注意的是,assert语句一般用于开发时对程序条件的验证,只有当内置debug为True时,assert语句才有效。当Python脚本以-O选项编译成为字节码文件时,assert语句将被移除。
    但与raise语句不同的是,assert语句是在条件测试为假时,才引发异常。assert语言的一般形式如下:

assert<条件测试>,<异常附加数据>#其中异常附加数据是可选的

常用异常
AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x
IOError 输入/输出异常;基本上是无法打开文件
ImportError 无法引入模块或包;基本上是路径问题或名称错误
IndentationError 语法错误(的子类) ;代码没有正确对齐
IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
KeyError 试图访问字典里不存在的键
KeyboardInterrupt Ctrl+C被按下
NameError 使用一个还未被赋予对象的变量
SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
TypeError 传入对象类型与要求的不符合
UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,
导致你以为正在访问它
ValueError 传入一个调用者不期望的值,即使值的类型是正确的
  • 更多异常
ArithmeticError
AssertionError
AttributeError
BaseException
BufferError
BytesWarning
DeprecationWarning
EnvironmentError
EOFError
Exception
FloatingPointError
FutureWarning
GeneratorExit
ImportError
ImportWarning
IndentationError
IndexError
IOError
KeyboardInterrupt
KeyError
LookupError
MemoryError
NameError
NotImplementedError
OSError
OverflowError
PendingDeprecationWarning
ReferenceError
RuntimeError
RuntimeWarning
StandardError
StopIteration
SyntaxError
SyntaxWarning
SystemError
SystemExit
TabError
TypeError
UnboundLocalError
UnicodeDecodeError
UnicodeEncodeError
UnicodeError
UnicodeTranslateError
UnicodeWarning
UserWarning
ValueError
Warning
ZeroDivisionError

你可能感兴趣的:(正则表达式和re模块)