正则表达式

一、在python中, 使用正则表达式, 需要导入re模块

import re

二、普通字符匹配, 使用findall

1 #字符匹配, 普通字符
2 #findall: 返回所有满足条件的列表集合
3 r = re.findall("alex", "afdafalexfqerqwrqwalexo")
4 print(r)

返回结果:

['alex', 'alex']

三、元字符
常用的元字符如下:

. ^ $ * + ? { }  [ ] | ( ) \

  a) . 的用法

#  . : 匹配的是除了换行符以外的任意字符, 一个点代表一个字符
print( re.findall( "lxl.l", "fqewruolxlwlqwelxlxl" ) )
print( re.findall( "lxl..l", "fqewruolxlewlqwelxlxl" ) )

   执行结果

['lxlwl', 'lxlxl']

  b) ^的用法

#   ^:以**开始的字符串
print( re.findall( "^lxl", "lxlqrqreqlxlasss" ) )

  执行结果

['lxlewl']

  c) $的用法

#   $:以**结尾的字符串
print( re.findall( "lxl$", "rqreqlxlassslxl" ) )

  执行结果

['lxl']

  d) * 的用法

print( "===   *: 匹配前面的字符出现0个或多个字符 (贪婪匹配)  =====" )
print( re.findall( "lxl*", "afdafdlxl" ) )
print( re.findall( "lxl*", "afdafdlxlaaa" ) )
print( re.findall( "lxl*", "afdafdlxlllllllsvblxbbblxl" ) )

  执行结果:

['lxl']
['lxl']
['lxlllllll', 'lx', 'lxl']

  e) + 的用法

print( "===   +: 匹配前面的字符出现1个或多个字符 (贪婪匹配)  =====" )
print( re.findall( "lxl+", "afdafdlxaaaalxlllll" ) )
print( re.findall( "lxl+", "afdafdlxlaaa" ) )
print( re.findall( "lxl+", "afdafdlxlllllllsvblxbbblxl" ) )

  执行结果:

['lxlllll']
['lxl']
['lxlllllll', 'lxl']

  f) ? 的用法

print( "===   ?: 匹配前面的字符出现0个或1个字符(贪婪匹配)  =====" )
print( re.findall( "lxl?", "afdafdlxlaaaalxlllll" ) )
print( re.findall( "lxl?", "afdafdlx" ) )
print( re.findall( "lxl?", "afdafdlxlllllllsvblxbbblxl" ) )

  执行结果:

['lxl', 'lxl']
['lx']
['lxl', 'lx', 'lxl']

  g) \ 的用法

print( "===   \: a. 反斜杠后面跟元字符,去除特殊功能. "
       "         b. 反斜杠后面跟普通字符, 实现特殊功能  "
       "         c. 引用序号对应的组所匹配的字符串"
       "=====" )
'''
    \d: 匹配任何十进制数, 他相当于使用字符集[0-9]
    \D: 匹配任何非数字字符,  他相当于使用字符集[^0-9]
    \s: 匹配任何空白字符, 他相当于[ \t\n\r\f\v]
    \S: 匹配任何非空白字符, 它相当于 [^ \t\n\r\f\v]
    \w: 匹配任何字母数字字符, 相当于 [a-zA-Z1-9_]
    \W: 匹配任何非字母数字字符, 相当于[^a-zA-Z1-9_]
    \b: 匹配一个单词边界, 也就是单词和空格间的位置
    
    
'''
print( re.findall( "\d", "a2ff3a,aaa^lx3$lll6sll" ) )
print( re.findall( "\D\D", "a2ff3a,aaa^lx3$lll6sll" ) )
print( re.findall( "\w", "a2ff3a,aaa^lx3$lll6sll" ) )
print( re.findall( "\W", "a2ff3a,aaa^lx3$lll6sll" ) )
print( re.findall( "\s", "a2ff3a, aaa^lx3$lll6sll" ) )
print( re.findall( r"\babc\b", " abc sfasfqerqwrfasf" ) )


print( "======    c. 引用序号对应的组所匹配的字符串    =======" )

# 分析: 第一个组是alex,第二组是eric, 然后后面接com. \2表示在这个位置匹配第二个组的内容
print( re.search( r"(alex)(eric)com\2", "alexericcomeric" ).group() )

 

print( "===   {}: 手动设置匹配字符出现的个数  =====" )
print( re.findall( "lxl{1}", "afdafdlxlaaaalxlllll" ) )
print( re.findall( "lxl{1,5}", "afdafdlxlllxasdfqlxlioplxlliiiilxlllllll" ) )
print( re.findall( "lxl{0}", "afdafdlxlllllllsvblxbbblxl" ) )
print( "===   (): 将其里面的内容作为一个组  =====" )
print( re.findall( "lxl{1}", "afdafdlxlaaaalxlllll" ) )
print( re.findall( "lxl{1,5}", "afdafdlxlllxasdfqlxlioplxlliiiilxlllllll" ) )
print( re.findall( "lxl{0}", "afdafdlxlllllllsvblxbbblxl" ) )
print( "===   []: 字符集. 选择性匹配[]中的内容  =====" )
print( re.findall( "a[bc]d", "wwwabd" ) )
print( re.findall( "a[bc]d", "wwwacd" ) )
print( re.findall( "a[bc]d", "wwwabcd" ) )
print( re.findall( "a[bc]d", "wwwad" ) )
# 注意: 当前面说的. ? + * 放到字符集[]里面就失去意义了
print( re.findall( "a[.]d", "wwwaqd" ) )
print( re.findall( "a[.]d", "wwwa.d" ) )
# 但是,有几个字符在字符集里还是有特殊意义的
      # 1. - :表示从哪到哪, 例如a-z, 从a到z; 1-9, 从1到9
print( re.findall( "a[a-z]m", "reqwasmadfazmfasm" ) )
      # 2. ^ : 表示除了***,即取非.
print( re.findall( "a[^1-9]", "fafa2adfa0fadfa8fafda3afa0" ) )
      # af ad ad  af af

      # 3. \ : 保留其自身的含义.
print( re.findall( "\d", "adfa312dfa9adf83dfa-98" ) )

  h) 贪婪模式

print( "===   贪婪模式: * + ?都是贪婪模式, 如果去最小,则加一个?  =====" )
# + 贪婪模式取最多
print( re.findall( "a\d+", "a25423bqa3423dsfa967a" ) )

# +? 则最小匹配
print( re.findall( "a\d+?", "a25423bqa3423dsfa967a" ) )
print( re.findall( "a\d*?", "a25423bqa3423dsfa967a" ) )

# 如果?后面还有内容, 则不能做到最小匹配
print( re.findall( "a\d+?b", "a25423bqa3423dsfa967a" ) )
print( re.findall( "a\d*?b", "a25423bqa3423dsfa967a" ) )

  i) re 模块常用方法

'''
re.findall:有() 匹配的是()里的内容  
re.search: 找符合条件的第一个,第一个可以在任何位置
re.match:尝试从字符串的起始位置匹配一个模式, 如果不是起始位置匹配成功, match返回none
re.sub: 替换
re.subn: 替换后返回替换次数
re.compile: 编译
re.split: 分割
re.finditer: 类似于findall, 不同之处在于finditer返回的是一个迭代器
'''

  

# findall 找到符合条件的全部字符串de集合
print( re.findall( "abc", "a25423bqabc3423dsfa967abc" ) )  # 返回 :['abc', 'abc']

# search 找到符合条件的第一个, 可以在任何位置的第一个. 如果没有匹配,返回None
print( re.search( "abc", "a25423bqa3423abcdsfa967abc" ).group() )  # 返回:abc
print( re.search( "abc", "ab" ) )  # 返回:None

# match 找到符合条件的第一个, 必须在开头位置
print( re.match( "com", "abccomddd" ) )  # 返回None
print( re.match( "com", "comabcddd" ).group() )  # 返回com
# 注意: 一旦search和match匹配成功以后, 就会返回一个match object对象,
# 而match object对象有以下方法
'''
      .start()返回匹配开始的位置
      .end() 返回匹配结束的位置
      .span() 返回一个元祖包含匹配(开始,结束)的位置
      ·group()返回被RE匹配的字符串, 可以传递一个或多个参数,返回对应组号匹配的字符串
'''

a = "abc123def"
print( re.match( "([a-z]*)([1-9]*)([a-z]*)", a ).group() )  # 匹配全部内容 结果:abc123def
print( re.match( "([a-z]*)([1-9]*)([a-z]*)", a ).group( 0 ) )  # 默认参数是0, 和没有参数结果一致
print( re.match( "([a-z]*)([1-9]*)([a-z]*)", a ).group( 1 ) )  # 获取第一个组的内容   结果:abc
print( re.match( "([a-z]*)([1-9]*)([a-z]*)", a ).group( 2 ) )  # 获取第二个租的内容  结果:123
print( re.match( "([a-z]*)([1-9]*)([a-z]*)", a ).group( 2, 3 ) )  # 获取第二个,第三个组的内容  结果:('123', 'def')

matchObject = re.match( "([a-z]*)([1-9]*)([a-z]*)", a )
# .start  第二个组的开始位置  返回结果: 3
print( matchObject.start( 2 ) )
# end 第一个组的结束位置  返回结果:3
print( matchObject.end( 1 ) )
# span 第二个组开始位置和结束位置   返回结果是(3, 6)
print( matchObject.span( 2 ) )

  

# re.sub: 替换
# re.sub(pattern, repl, str, max=0, flags=0)
# re.sub("查找字符串","替换后的字符串","字符串","替换次数,默认是0,全部替换", 替换模式)
print( re.sub( "g.t", "have", "I get you, I got me, I forgot u", 2 ) )  # 结果: I have you, I have me, I forgot u

# re.subn: 替换, 并返回一个元祖, (替换结果, 替换次数)
# re.subn(pattern, repl, str, max=0, flags=0)
# re.subn("查找字符串","替换后的字符串","字符串","替换次数,默认是0,全部替换", 替换模式)
print( re.subn( "g.t", "have", "I get you, I got me, I forgot u", 2 ) )  # 结果: ('I have you, I have me, I forgot u', 2)

# re.compile: 给定一个正则表达式 pattern,指定使用的模式 flags 默认为0 即不使用任何模式,
# 然后会返回一个 SRE_Pattern (参见 第四小节 re 内置对象用法) 对象
# 当多次调用的时候, 这个方法效率更高
reg = re.compile( ".+" )
print( reg.findall( "s" ) )

# re.split: 分割
# split(pattern, string, maxsplit=0, flags=0)
reg = re.compile( r"\d+" )
print( reg.split( "fafafa2dfad4fadsf153uou", 2 ) )  # 返回结果: ['fafafa', 'dfad', 'fadsf153uou']
# 上面写法和下面等价
print( re.split( r"\d+", "fafafa2dfad4fadsf153uou" ) )  # 返回结果: ['fafafa', 'dfad', 'fadsf', 'uou']
print( re.split( "[bc]", "abcd" ) )  # 从前往后, 一个一个分割. 有顺序.  结果: ['a', '', 'd']


# re.finditer 参数和作用与 findall 一样,不同之处在于 findall 返回一个列表, finditer 返回一个迭代器
fi = re.compile("\d+")
ite = fi.finditer("fafda2fadfadsf3422adfafa131dfadfa")
for item in ite:
      print(item.group(),item.span())

  j) 匹配模式

# 正则表达式匹配模式   --  可选标志flags, 默认是0
# re.search(pattern, string, flags=0)
# re.findall(pattern, string, flags=0)
# re.match(pattern, string, flags=0)

# re.I: 忽略大小写
print( re.match( "com", "CoM" ) )  # 结果None
print( re.match( "com", "CoM", re.I ).group() )  # 结果: CoM

# re.S: 改变.的匹配行为.   正常.是匹配除了换行符之外的所有字符. 使用re.S模式后, 匹配包括.在内的所有字符
print( re.findall( ".", "a$ d\n3a" ) )  # 不包含换行符,  返回结果: ['a', '$', ' ', 'd', '3', 'a']
print( re.findall( ".", "a$ d\n3a", re.S ) )  # 包含换行符,  返回结果: ['a', '$', ' ', 'd', '\n', '3', 'a']

  k) 原生字符串

#regstr:原生字符串
print(re.findall("\\\\","abc\com")) # \有特殊含义, python需要转换一次, 正则表达式还要在转换一次, 所有需要四个\\\\
print(re.findall(r"\\","abc\com")) #而使用了原生字符r以后, 就避免了多次转换. 只需转换一次, 即正则表达式转换

  l ) 优先捕获

#优先捕获
#在findall里面,如果正则表达式有()也就是组, 则优先取得组的内容.
print(re.findall("www.(baidu|sina).com","www.baidu.com")) # 结果返回: baidu
#在组的前面加一个?: 则去掉优先捕获
print(re.findall("www.(?:baidu|sina).com", "www.baidu.com"))  #返回结果:www.baidu.com

 

posted @ 2017-07-12 15:59  盛开的太阳  阅读(429)  评论(0编辑  收藏  举报