Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python 正则表达式 #53

Open
w4096 opened this issue Feb 26, 2019 · 3 comments
Open

Python 正则表达式 #53

w4096 opened this issue Feb 26, 2019 · 3 comments

Comments

@w4096
Copy link
Owner

w4096 commented Feb 26, 2019

@w4096
Copy link
Owner Author

w4096 commented Feb 26, 2019

部分正则语法

=> r"\n" 表示两个字符 \n,而 "\n" 表示一个字符,即换行符。

=> {m,n}? 匹配尽可能少的字符

=> [] 用来表示一组字符,在 [] 中特殊字符失去它们特殊的含义,即 [(+*)] 就匹配 ( + * ) 这四个字符。

=> [^5] 匹配所有不是 5 的字符,[^^] 匹配所有不是 ^ 的字符,在 [] 中,如果 ^ 不是第一个字符,那么它就没有特殊意义。

=> (?aiLmsux) 放在正则表达式前,用来开启正则表达式标志,这个表达式匹配空字符串。其中 'a' 表示 re.A,'i' 表示 re.I ……

re.match(r'(?i)ab|AB', 'aB')

=> (?:...) 表示不捕获,有时候需要使用括号,但是又不想捕获分组,这个时候可用此法。

=> (?P<name>...) 用来给一个分组进行命名,一个正则表达式中如果有多个分组,尤其是分组之间有嵌套的时候,后向引用分组的时候,使用数字就显得很麻烦且容易出错,而给一个分组命名后,就方便引用了。引用的时候使用 (?P=name) 即可。

re.match(r'(?P<underscore>_{1,2})abc(?P=underscore)', '__abc__')

=> (?#...) 这里表示一个注释,括号中的内容会被忽略。

=> (?=...) 前向断言,如下例子,只匹配后面跟着 defabc

re.match(r'abc(?=def)', 'abcdef')

=> (?!...) 如下,匹配后面不跟 dabc

re.match(r'abc(?!d)', 'abce')

=> (?<=...)(?<!...)

>>> m = re.search('(?<=abc)def', 'abcdef')
>>> m.group(0)
'def'

=> (?(id/name)yes-pattern|no-pattern)

这里 id/name 表示一个分组的编号或者名称,即如果此前这个分组已经匹配到了,那么就匹配 yes-pattern 否则匹配(可选)no-pattern

>>> re.match(r'(<)?(\w+@\w+(?:\.\w+)+)(?(1)>|$)', '[email protected]').group(0)
<<< '[email protected]'

>>> re.match(r'(<)?(\w+@\w+(?:\.\w+)+)(?(1)>|$)', '<[email protected]>').group(0)
<<< '<[email protected]>'

这里如果前面的 < 有匹配上,那么结尾就要匹配一个 > 否则匹配 $

=> \A,匹配字符的开头,这和 ^ 是有差别的,\A 只会匹配一个位置,那就是字符串开头。而 ^ 在多行模式下,可以匹配每一行的开头。

=> \Z 匹配字符的结尾。

=> \b,匹配 \W\w 的边界,如 re.search(r'ABC\b', 'ABC>')

=> \B,匹配 \w\w 或者 \W\W 的边界。

=> \d\D 分别匹配数字和非数字。

=> \s 匹配空白符,即 [\t\n\r\f\v]

=> \S 匹配非空白,即 [^\t\n\r\f\v]

=> \w 匹配字符,ASCII 范围内等价于 [a-zA-Z0-9]

=> \W 匹配非 \w

@w4096
Copy link
Owner Author

w4096 commented Feb 26, 2019

re 模块

=> re.compile

返回一个正则表达式对象,上面有很多下面介绍的在 re 模块上包含的方法。

re.compile(pattern, flags=0)
<<< r = re.compile(r'<(\d+)>')
<<< r.match('<323>').groups()
>>> ('323',)

=> re.search

在字符中搜索匹配的 pattern,如果有匹配则返回 match object,否则返回 None。

match = re.search(pattern, string)
if match:
    process(match)

=> re.match

如果字符串的开头与 pattern 匹配,则返回 match object,否则返回 None。

re.match(pattern, string, flags=0)

如果整个字符串都匹配,则返回 match object

re.fullmatch(pattern, string, flags=0)

=> re.split,使用正则表达式对字符串进行切分。

re.split(pattern, string, maxsplit=0, flags=0)

如果用于切分的正则表达式中包含分组,那么分组捕获的内容也会返回。

>>> re.split(r'<->', '123<->456<->789')
<<< ['123', '456', '789']

>>> re.split(r'<(-)>', '123<->456<->789')
<<< ['123', '-', '456', '-', '789']

=> re.findall

返回所有匹配的子字符串。

<<< re.findall(r'\d{3}', '123<->456<->789')
>>> ['123', '456', '789']

# 含有多个分组的时候,返回的是元组的列表
<<< re.findall(r'(\d)\d(\d)', '123<->456<->789')
>>> [('1', '3'), ('4', '6'), ('7', '9')]

=> re.finditer

返回 match object 的迭代器,由此可以得到所有的匹配项,用于处理较长的文本。

=> re.sub

这个方法用来从源字符串中匹配部分内容,然后通过一个模板构成新的字符串。

re.subn(pattern, repl, string, count=0, flags=0)

举例子,比如用 123->456 构造出 '456<-123'

pattern 部分匹配 123456,然后 repl 部分使用匹配项,拼凑出目标字符串。

这里 repl 是一个字符串,要想使用 pattern 匹配的分组,可以使用 \1 这样的写法,对于命名分组,可以使用 \g<name> 这样的写法。

>>> re.sub(r'(?P<from>\d{3})->(?P<to>\d{3})', '\g<to><-\g<from>', '123->456')
<<< '456<-123'

@w4096
Copy link
Owner Author

w4096 commented Feb 26, 2019

Match 对象

=> Match.expand

<<< match = re.search(r'<(?P<name>\w+)@(\w+)\.(\w+)>', '<[email protected]>')
<<< match.expand('mailto:\g<name>[at]\g<2>[dot]\g<3>')
>>> 'mailto:wangyu[at]163[dot]com'

=> Match.group

<<< match = re.search(r'<(?P<name>\w+)@(\w+)\.(\w+)>', '<[email protected]>')
<<< match.group(0) # or match.group()
>>> '<[email protected]>'

<<< match.group(0,1,2,3)
>>> ('<[email protected]>', 'wangyu', '163', 'com')

=> Match.groups

以元组的形式返回所有分组。

<<< match.groups()
>>> ('wangyu', '163', 'com')

=> Match.groupdict

以字典的形式返回所有命名分组,未命名的分组会被忽略。

<<< match = re.search(r'<(?P<name>\w+)@(?P<host>\w+.\w+)>', '<[email protected]>')
<<< match.groupdict()
>>> {'name': 'wangyu', 'host': '163.com'}

=> Match.start / Match.end

返回匹配的分组的起始和结束位置。

<< match = re.search(r'<(?P<name>\w+)@(?P<host>\w+.\w+)>', '<[email protected]>')
<<< match.start(),match.start(1),match.start(2)
>>> (0, 1, 8)

<<< match.end(),match.end(1),match.end(2)
>>> (16, 7, 15)

=> Match.span

返回指定分组的起始和结束位置。

<<< match.span(),match.span(1),match.span(2)
>>> ((0, 16), (1, 7), (8, 15))

@w4096 w4096 transferred this issue from another repository Mar 22, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant