Python 正则
Python 正则
在带有 'r'
前缀的字符串字面值中,反斜杠不必做任何特殊处理。 因此 r"\n"
表示包含 '\'
和 'n'
两个字符的字符串,而 "\n"
则表示只包含一个换行符的字符串。 模式在 Python 代码中通常都使用原始字符串表示法。
1. findall
提取js中定义的变量
def demo1():
"""
从字符串中提取js变量
:return:
"""
test_str = """
<script>
var detail_params = {
aggID: "abcdefg",
tagAggId: "123456789"
};
</script>
"""
# findall 在字符串中找到正则表达式所匹配的所有子串,并返回一个列表; 如果匹配的字符串非常多, 可以使用finditer, 返回一个迭代器以节省内存
# \s+ 匹配任意空白字符,至少匹配一次
# \s* 匹配任意空白字符,0次或多次; 以应对有些情况没有空格或者多个空格的情况
# .*? 匹配任意字符,0次或多次,非贪婪模式(尽可能少的匹配字符)
# re.DOTALL 或者 re.S 使 . 匹配包括换行符在内的任意字符(默认不包括换行符)
detail_params = re.findall(r'var\s+detail_params\s*=\s*(.*?);', test_str, re.S)
# 键并不是字符串,所以不能直接使用json.loads, 需要使用execjs.eval以js代码解析
detail_params = execjs.eval(detail_params[0])
print(detail_params)
print(detail_params['aggID'])
2. search
提取调用函数中的参数
def demo2():
test_str = """
pagenav(66, "/a/b/c/d/")
"""
# re.search 匹配整个字符串,直到找到一个匹配。 一个匹配对象!, findall是找出所有匹配对象
# \( 字符串中原本的括号需要转义
# () 括号内的内容会被分组
# \d+ 匹配数字,至少匹配一次
# group(1) 返回第一个括号内的内容,group()/group(0)返回整个匹配的内容
page = re.search(r'pagenav\((\d+),\s*".*?"\)', test_str).group(1)
print(page)
# 匹配两个参数
# groups() 以元祖形式返回所有括号内的内容
params = re.search(r'pagenav\((\d+),\s*"(.*?)"\)', test_str).groups()
print(params)
3. match
正则表达式中的特殊字符需要转义
def demo3():
str1 = """
window.ansFrontendGlobals.earlySettings = [{"id": 1, "name": "Tiam"}];
"""
# re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。
# 使用 """ 定义字符串时, 前后会有换行符, 所以需要\s*匹配前后的空白字符!!!否则必定匹配失败
early_settings = re.match(r'\s*window.ansFrontendGlobals.earlySettings = (.*?);\s*', str1)
print(early_settings.group(1))
str2 = 'window.ansFrontendGlobals.earlySettings = [{"id": 1, "name": "Tiam"}];'
early_settings = re.match(r'window.ansFrontendGlobals.earlySettings = (.*?);', str2)
print(early_settings.groups())
# 通常使用 re.match 用以判断字符串是否符合正则表达式
# *, +, ?, |, [, {, ), 需要转义; ", ', ., /, \ 不需要转义
if es := re.match(
r'hello there have some special character: "\*\+\?\|\[\{\)\n, they not need escape: "./',
'hello there have some special character: "*+?|[{)\n, they not need escape: "./'
):
# span() 返回一个元组包含匹配的开始和结束的索引
print('该字符串符合正则表达式:', es.span())
4. complie sub
合法化 字符串为合法文件名
def demo4():
"""
替换文件名中的非法字符
:return:
"""
# 一个非法文件名
filename = '?abc/def:ghi>jkm.pdf'
# re.compile 编译正则表达式,生成一个正则表达式对象, 以便在后面的匹配中复用
pattern = re.compile(r'[\\/:*?"<>|]')
# 替换非法字符
# re.sub 替换所有正则匹配的字符串
filename = pattern.sub('_', filename)
print(filename)
# 还有个问题,文件名中可能包含换行符\n \t 等, 上面的正则表达式无法匹配导致文件名无法创建
filename = 'I\tam a good boy \n.txt'
filename = pattern.sub('_', filename)
print(filename)
# OSError: [Errno 22] Invalid argument: 'I\tam a good boy \n.txt'
# with open(filename, 'w') as f:
# f.write('Hello, world!')
# 表达式中添加\n \t即可替换
filename = re.sub(r'[\\/:*?"<>|\n\t]', '_', filename)
print(filename)
5. split
def demo5():
# 分离url中的关键字
url = 'https://www.renrendoc.com/search.html?q=girls&figure=hot'
keywords = re.split(r'[:/.?=&]', url)
print(keywords)
6. escape
转义 pattern 中的特殊字符。
def demo6():
# 关于转义
text = 'hello there have some special character: "*+?|[{)\n, they not need escape: "./'
escape_text = re.escape(text)
if match := re.match(escape_text, text):
print('该字符串符合正则表达式:', match.span())
else:
print('该字符串不符合正则表达式')
修饰符 - 可选标志
修饰符 | 描述 |
---|---|
re.I | 使匹配对大小写不敏感 |
re.L | 做本地化识别(locale-aware)匹配 |
re.M | 多行匹配,影响 ^ 和 $ |
re.S | 使 . 匹配包括换行在内的所有字符 |
re.U | 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B. |
re.X | 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。 |
更多标志相关信息: re — 正则表达式操作 — Python 3.13.0 文档
特殊字符类
. | 匹配除 “\n” 之外的任何单个字符。要匹配包括 ‘\n’ 在内的任何字符,请使用象 ‘[.\n]’ 的模式。 |
---|---|
\d | 匹配一个数字字符。等价于 [0-9]。 |
\D | 匹配一个非数字字符。等价于 [^0-9]。 |
\s | 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。 |
\S | 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。 |
\w | 匹配包括下划线的任何单词字符。等价于’[A-Za-z0-9_]'。 |
\W | 匹配任何非单词字符。等价于 ‘[^A-Za-z0-9_]’。 |
更多
Python re
模块学习:
- 正则表达式指南 — Python 3.13.0 文档
- Python 正则表达式 | 菜鸟教程 (runoob.com)
正则表达式学习:
- Regex Learn - Playground
- regex101: build, test, and debug regex