Python正则表达式(基本规则)

Python的正则表达式的模块是re,它的基本语法的规则就是指定一个字符序列,比如:

>>>import re

>>>s='123abc456abce789'

>>>re.findall(r'abc',s)      #在s字符串里找到所有的abc,并把他们放到列表list里

以上运行结果就是:['abc','abc']


re规定了若干语法规则:

1)功能字符:'.'    '*'  '+'  '|'  '?'  '^'  '$'  '\' 等。

    '/':  转义引导符号。

2)规则分界符:'['  ']'  '('  ')'  '{' '}'等几种特殊括号

3)预定义转义字符集:‘\d’  '\w'  '\s'等等,他们是以字符 '\'开头,后面接一个特定的字符形式,用来指示一个预定。

4)其他特殊功能字符:'#'  '!'  ':'  '-' 等,他们只在特定的情况下表示特殊的含义,比如  (?#...)  就表示一个注释,里面的内容会被忽略掉。

1.0 通配符

'.'  匹配1个任意字符(但不包括换行符\n)

'\d' 匹配1个数字,等价于[0-9]

'\D' 是'\d'的反义词,等价于[^0-9]

'\w' 匹配1个字母或数字,等价于 '[a-zA-Z0-9]'

'\W' 是'\w' 的反义词,等价于'[^a-zA-Z0-9]'

'\s' 匹配一个空白符,等价于'[ \t\n\r\v\f](注意含空格);


1.1  '[  ]' 表示集合

1)  '-' 用在字母或者数字之间表示一个区间,如下:
'[a-z]'  表示匹配所有的小写英文字母

'[A-Z]'  表示匹配所有的大写英文字母

'[a-zA-Z]'  表示匹配所有的大小写英文字母

'[0-9]'    表示匹配0-9的所有数字

ps:'[z-a]' 写法错误,顺序不能颠倒

2)'^'  在开头表示“非”,其他位置则表示他本身,如下:

'[^a-zA-Z]'  表示匹配所有英文字母

'[a-z^A-Z]'    表示匹配所有英文字母和字符 '^'

3)'|'  表示“或”,将两个规则并列起来,匹配其中之一就可以了,如:

'[a-zA-Z]|[0-9]' 相当于 '[a-zA-Z0-9]'  表示匹配所有的字母和数字

1.2  重复

'*'  0或多次匹配(前面的规则)

'+'  1次或多次匹配    (至少一次,可以多次匹配)>=1

'?'  0或1次匹配    (只匹配前面的规则0次或1次)

例1:匹配以下字符串中的前一部分是字母,后一部分是数字或是没有变量的名字。

>>>s='aaa bbb111 cc22cc 33dd'

>>>re.finall(r'\b[a-z]+\d*\b',s)

      ['aaa','bbb111'] 

#匹配至少一个字母开头([a-z]+),以连续数字结尾或没有数字(\d*)


>>>re.findall(r'[a-z]'+\d*',s]

['aaa','bbb111','cc22','cc','dd'] 

#与上面相比,无'\b'边界,会把单词给拆开

例2:匹配一个数字,这个数字可以是一个整数,也可以是一个科学计数法记录的数字,比如123和10e3都是正确的数字。

>>>s='123 10e3 20e4e4 30ee5'

>>>re.findall(r'\b\d+[eE]?\d*\b',s) 

  ['123','10e3']

#'\b\d+[eE]?\d*\b'拆开来看就是:'\b'前后都有边界 ,开头'\d+' (至少一个数字), 然后'[eE]?' (没有或1个e、E ), 结尾'\d*'(没有或者多个数字);


1.3精确匹配和最小匹配  '{  }'

1.3.1精确匹配规则如下:
'{m}'  精确匹配m次 ,如: '{3}'

'{m,n}'  匹配最少m次,最多n次 (m

'{m,}'    只匹配最少m次 ,如: '{3,}'

'{,n}'  只匹配最多n次,如: '{,5}'

例:寻找下面的字符串

      a:3位数

    b:2位数到4位数

    c:5位数以上数

    d:4位数以下的数

>>>s='1 22 333 4444 55555 666666'

>>>re.findall(r'\b\d{3}\b',s)    #a:3位数

['333']

>>>re.findall(r'\b\d{2,4}\b',s)  # b:2位数到4位数

['22','333','4444']

>>>re.findall(r'\b\d{5,}\b',s)  # c:5位数以上数

['55555','666666']

>>>re.findall(r'\b\d{,4}\b',s)  # d:4位数以下的数

['1','22','333','4444']


1.3.2  '*?'  '+?'  '??' 最小匹配

s=r'/*part1*/code/*part2*/'    #此为一个c语言的注释

#如果使用最大规则:

>>>re.findall(r'/\*.*\*/',s)

['/*part1*/code/*part2*/']    #结果把整个字符串都写进去了


>>>re.findall(r'/\*.*?*\*/',s)    #'*?'表示尽可能少的匹配

['/*part1*/','/*part2*/'] 

#ps:'/\*.*?*\*/',其中'/\*'是匹配'*'本身,'.'表示匹配除换行符'\n'外的所有字符,'.*'表示匹配0或多次换行符'\n'外的所有字符,而'.*?'表示匹配尽可能少的匹配0或多次换行符'\n'外的所有字符,就是part1和part2部分。

1.4  其他规则

>>>s='123\n456\n789'

>>>re.findall(r'.+',s)  #至少1次('+')匹配除换行符\n外的所有字符

['123','456','789']

>>>re.findall(r'.+',s,re.S)  #加上大写的S,则匹配含\n的所有字符

['123\n456\n789']

>>>s='12 34\n56 78\n90'

>>>re.findall(r'^\d+',s,re.M)    #至少1次('+')匹配位于行首('^')的数字(\d')

['12','56','90']

>>>re.findall(r'\d+$',s,re.M)    #至少1次('+')匹配位于行尾('$')的数字(\d')

['34','78','90']

>>>re.findall(r'\A\d+',s,re.M)    #至少1次('+')匹配位于字符串开头('\A')的数字(\d')

['12']

>>>re.findall(r'\d+\Z',s,re.M)    #至少1次('+')匹配位于字符串最后('\Z')的数字(\d')

['90']

>>>s='abc abcde bc bcd'

'\b'  匹配单词边界

>>>re.findall(r'\bbc\b',s)

['bc']        #匹配一个独立的单词'bc',而当它是其他单词的一部分的时候,不匹配


'\B'  匹配非边界

>>>re.findall(r'\Bbc\W+',s)    #匹配包含'bc'但不以‘bc’开头,并且后面至少有一个字母或数字的单词

['bcde']    #成功匹配了'abcde'中的'bcde',而没有匹配'bcd'


>>>re.findall(r'\sbc\s',s)  #匹配一个独立的单词bc

[' bc ']    #不过输出的bc前后会有空格

'(?:)' 无捕获组

例:匹配字符串中重复的'ab'

>>>s='ababab abbabb aabaab'

>>>re.findall(r'\b(?:ab)+\b',s)

['ababab']


>>>re.findall(r'\b(ab)+\b',s)  #只用一个括号,就相当于一个组(grou)

['ab']    #ps:关于组后面会详细介绍

'(?#)'  注释

python允许你在正则表达式中注释,在'(?#'和')'中的内容将会被忽略


2.界定

'(?<=...)'  前向界定

'(?=...)'    后向界定

ps:括号中的'...'代表你希望匹配的字符串的前面、后面应该出现的字符串

例:你希望找出C语言注释中的内容,他们是否包含在'/*'和'*/'之间,不过你并不希望匹配的结果把'/*'和'*/'也包括进来,那么你可以这样用。

>>>s=r'/*comment1*/code/*comment2*/'

>>>re.findall(r'(?<=/\*).+?(?=\*/)',s)  #匹配字符前面是'/*'后面是'*/'的字符

['comment1','comment2']


ps:前向界定的表达式必须是常值,不过可以在后向界定写正则,如下所示:

>>>s='aaa111aaa,bbb222,333ccc'

>>>re.findall(r'(?<=[a-z]+)\d+(?=[a-z]+)',s)    #此用法错误,前向界定里不能用正则

error:look-behind requires fixed-width pattern.    #结果报错了

>>>re.findall(r'\d+(?=[a-z]+)',s)  #后面的界定可以用正则

['111','333']    #界定是包含在结果中的

ps:如果你一定要匹配夹在字母中间的数字,你可以使用组(group)的方式,如:

>>>re.findall(r'[a-z]+(\d+)[a-z]+',s)  #规则内,组以外的会被忽略

['111']

'(?#只有当你希望的字符串前面不是'...'的内容才匹配

'(?!...)'  后向非界定    #只有当你希望的字符串后不跟着'...'的内容才匹配

s='aaa111aaa,bbb222,333ccc'

>>>re.findall(r'\d+(?![a-z]+)',s)

['11','222','333']

>>>re.findall(r'\d+(?!\w+)',s)  #匹配数字后面不跟着字母或者数字

['222']


3.组的基本知识

1) '('  ')'  无命名组

>>>s='aaa111aaa,bbb222,333ccc'

>>>re.findall(r'[a-z]+(\d+)[a-z]+',s)    #一个组

['111']  #只返回了匹配包含在'( )'里的

>>>s='aaa111aaa,bbb222,333ccc,444ddd444,555eee666,fff777ggg'

>>>re.findall(r'([a-z]+)\d+([a-z)+',s)  #有两个组,找出中间夹有数字的字母

[('aaa','aaa'),('fff','ggg')] 

>>>re.findall(r'[a-z]+(/d+)([a-z]+)',s)

[('111','aaa'),('777','ggg')]    #有组的话,组以外的不返回

2) '(?p=name)'调用已匹配的命名组

ps:就是组命名,然后下次要使用相同的规则的组时候可以直接调用,如

>>>re.findall(r'(?p[a-z]+)\d(?p=gl)'  #找出被中间夹有数字的前后同样的字母

['aaa']

3)'\number' 通号调用已匹配的组

>>>re.findall(r'([a-z]+)\d+\1',s)  #找出被中间夹有数字的前后同样的字母

['aaa']

>>>s='111aaa222aaa111,333bbb444bb33'

>>>re.findall(r'(\d+)([a-z]+)(\d+)(\2)(\1)',s)  #找出完全对称的‘数字-字母-数字-字母-数字’

[('111','aaa','222','aaa','111')]  #注意'\number'与'(\number)'的区别,以及命名组调用的区别

4)'(?(id/name)yes-pattern}|no-pattern)'  判断指定组是否已匹配,执行相应的规则

>>>s='< usr1@mail1 > ursl2@mail2'

>>>re.findall(r'(<)?\s*(\w+@\w+)\s*(?(1)>)',s)

[('<','usr1@mail1'),('','ursl2@mail2')]

你可能感兴趣的:(Python正则表达式(基本规则))