符号
\b word boundary, \bdef 表示def,
^ 有两个意思,如果在[]里,一般表示exclude,比如[^<]表示除了<的所有char。另一个意思,如果它在开头,比如^MET,它表示开头的位置。与之对应的就是
$ 表示结尾,比如 ^MET$
? optional, 有或没有,比如-?,代表-或者没有
| 是或,a|b|c,就是这三个都可以
() capturing group; 把几个东西group到一起,比如([A-Z]+)就把大写的letter和+ group到了一起
(?: ...) non-capturing group, groups things together
, 0个或多个,比如(ab),可以是"", ab, ababab, abababab..
+, 1个或者多个,和*不一样,它必须要求至少一个
\s optional white space, \s* 很多空格也可以
[] character class,比如[A-Za-z0-9] any letter or number, [abc] one of a,b,c
\d 相当于 [0-9]
(?! ... $) 里面的..表示如果match,就不要
(?P<name>...) 给group取名字,比如(?P<cls>[^"]*) ,那么这个group的名字就叫cls
\g<name> refer group 名字(类似\1,\2,但是有名字的group),比如\g<cls>就是指上面的group
()是捕获组
没有()就会只return nan
df['aa']=df['info'].str.extract(r'-?\d+\s*(.*)')
import
import re
或者还有regex, 更多的功能
import regex as re
特殊字符
.
如果你想搜索字符 dot . 那么直接在pattern里放. 是不会work的。需要在前面放一个\来帮助escape(\是用来帮助escape特殊字符的,dot在regex里是特殊字符,所以用.来寻找真正的dot)
正常字符中,后斜线\总是有着特殊的含义,比如\n, \t等,并不会把\当做一个字符。想要证明\只是一个字符,必须用双后斜线\
print(r"Line1\nLine2") #返回Line1\nLine2
print("Line1\nLine2") # 返回Line1 Line2 换行
print("C:\name") # 普通字符串会把\name中的\n当成换行
print("C:\\name") # 返回 C:\name
用raw string r''可以把\当成一个字符。
print(r"C:\name") #返回 C:\name 不需要\\了
regex里,pattern前往往放r'',因为pattern中可能经常会有涉及后斜线的pattern,比如数字是\d 相当于[0-9],没有用raw string,就得是"\d"了。
regex functions
第一位永远是pattern, 第二位是string
注意re.match和re.search只返回第一个match。而findall,finditer, sub却可以返回所有的matches。
re.match
pattern必须在开头,否则返回None。
re.match('a', 'abbba').group() # output a
re.match('a', 'bbba') # nothing output
re.fullmatch
对于整个 string 都要 match,否则 不会 return 任何
AOC 2025 day2
re.fullmatch(r'(.+)\1+', str(121212))
# return <regex.Match object; span=(0, 6), match='121212'>
re.findall
返回list of strings
找到所有符合pattern的string,然后返回一个list of strings
re.findall('a','bbbbaba') # output ['a', 'a']
re.finditer
返回iterator
next(re.finditer('a','bbbbaba'))
# output <re.Match object; span=(4, 5), match='a'>
re.search
pattern可以在string里的任何地方,返回第一次出现的地方
re.search('a','bbbbaba') #<re.Match object; span=(4, 5), match='a'>
re.search('a','bbbbaba').group() # return a
re.search()里的pattern可以添加多个()用于capture
返回第一个capture, group(1)
re.search(r"(a)b(c)", "123abc456").group(1) # return a
返回第二个capture, group(2)
re.search(r"(a)b(c)", "123abc456").group(2) # 返回 c
返回全部,用groups()
re.search(r"(a)b(c)", "123abc456").groups() # 返回('a','c')
group
group(0)和group()相同, 返回full match
那么第一个match对应的就不是python的index0,而是group(1),以此类推
到groups(),就会返回每个match合成的tubples
m = re.search(r"(Y\d+)(C)", "Y1230C")
m.group() # full match,Y1230C
m.group(0) # full match,Y1230C
m.group(1) # first capture, Y1230
m.group(2) # second capture, C
m.groups() # all captures in tuples, ('Y1230','C')
pattern里如果没有()来capture group,那么就用m.group(0),如果有,就用m.group(1)
没有()的情况:
text = "met fak src"
def to_upper(m):
return m.group(0).upper() # m.group(0) = the matched string
result = re.sub(r"[a-z]+", to_upper, text)
print(result)
有()的情况:
text = "met fak src"
def to_upper(m):
return m.group(1).upper()
result = re.sub(r"([a-z]+)", to_upper, text)
print(result)
search flag
re.search()的第三个argument,是放flags的地方
一般搜索遇到\n就会停下来,如果加上re.DOTALL (dot-all) 就会每行都搜索,直到遇到你的pattern
re.search(pattern, txt, re.DOTALL | re.IGNORECASE)
IGNORECASE 会大小写无所谓,所以是ignore case (无视大小写)。
default是flags=0
re.compile
可以先compile pattern, 然后pattern.findall
比如:
PAT = re.compile(r"(\w+)\s+(\d+)\s+([\d.]+)\s+([\d.]+)\s+([\d.]+)\s+([\d.]+)\s+([\d.]+)\s+(\w?)")
matches = PAT.findall(text) # 返回list
#或者
for match in PAT.finditer(text):
re.sub
格式
re.sub(pattern, replacement, text)
例子
text = "K1230 is mutated."
re.sub(r"1230", "Y1230", text) # KY1230 is mutated.
如果要保留原有的,添加额外的,那就在replacement里放\1, 比如
if 'class=' in text_tag:
return re.sub(r'class="([^"]*)"', r'class="\1 hover-text"', text_tag)
如果第二个arg是function
text = "Y1230C"
def format_mutation(m):
site = m.group(1) # Y1230
mut = m.group(2) # C
return f"{site}->{mut}"
re.sub(r"(Y\d+)([A-Z])", format_mutation, text) #Y1230->C
backreferences
里面有\1, \2, \3可以让你重复使用被capture的group,\1代表group(1),以此类推
re.sub(r'(foo)(bar)', r'\2\1', 'foobar') # 返回barfoo