[tools] Regex

符号 \b word boundary, \bdef 表示def, ^ 有两个意思,如果在 里,一般表示exclude,比如 ^< 表示除了<的所有char。另一个意思,如果它在开头,比如^MET,它表示开头的位置。与之对应的就是 表示结尾,比如MET 表示结尾,比如^MET ? optional, 有或没有,比如 ?,代表 或者没有 | 是或,a|b|c,就是这三个都可以

符号

\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'>

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