Julia 正则表达式(Regex)完全指南(中文版)
“强大、原生、高性能” —— Julia 的正则表达式是文本处理的核武器
一、什么是正则表达式?
正则表达式(Regular Expression) 是一种用模式(pattern)匹配文本的工具。
Julia 中使用 Regex 类型,原生支持 PCRE(Perl 兼容正则表达式)引擎。
r"pattern" # 创建正则表达式
二、创建正则表达式
# 基本语法
r"abc" # 匹配 "abc"
r"\d+" # 匹配一个或多个数字
r"^hello" # 以 hello 开头
r"world$" # 以 world 结尾
r"\s" # 匹配空白字符
# 忽略大小写
r"julia"i # i = ignore case
# 多行模式
r"^start"m # m = multiline,每行开头
# 点匹配换行
r"."s # s = dotall
# 组合标志
r"pattern"ims
三、核心元字符(Metacharacters)
| 元字符 | 含义 | 示例 |
|---|---|---|
. | 匹配任意字符(除换行) | r"a.c" → “abc”, “axc” |
^ | 行首 | r"^abc" → 匹配行首 |
$ | 行尾 | r"abc$" |
* | 0次或多次 | r"a*" → “”, “a”, “aaa” |
+ | 1次或多次 | r"a+" → “a”, “aaa” |
? | 0次或1次 | r"a?" → “”, “a” |
{n} | 恰好 n 次 | r"a{3}" → “aaa” |
{n,} | 至少 n 次 | r"a{2,}" |
{n,m} | n 到 m 次 | r"a{2,4}" |
| | 或 | r"cat|dog" |
( ) | 分组 | r"(ab)+" → “ab”, “abab” |
[ ] | 字符集 | r"[a-z]" |
[^ ] | 否定字符集 | r"[^0-9]" |
四、字符类(Character Classes)
| 类 | 含义 |
|---|---|
\d | 数字 [0-9] |
\D | 非数字 |
\w | 单词字符 [a-zA-Z0-9_] |
\W | 非单词字符 |
\s | 空白字符(空格、制表、换行) |
\S | 非空白 |
\b | 单词边界 |
\B | 非单词边界 |
r"\d{4}-\d{2}-\d{2}" # 匹配日期 2025-10-26
r"\bcat\b" # 匹配独立单词 "cat",不匹配 "category"
五、常用匹配函数
| 函数 | 说明 | 返回值 |
|---|---|---|
occursin(r, s) | 是否包含 | Bool |
match(r, s) | 首次匹配 | RegexMatch 或 nothing |
eachmatch(r, s) | 所有匹配 | 迭代器 |
matchall(r, s) | 所有匹配字符串 | Vector{String} |
s = "Email: alice@example.com, bob@site.org"
# 1. 是否包含邮箱
occursin(r"\w+@\w+\.\w+", s) # true
# 2. 首次匹配
m = match(r"\w+@\w+\.\w+", s)
m.match # "alice@example.com"
m.offset # 7(起始位置)
m.captures # [](无分组)
# 3. 所有匹配
for m in eachmatch(r"\w+@\w+\.\w+", s)
println(m.match)
end
# alice@example.com
# bob@site.org
六、分组与捕获(Capturing Groups)
r = r"(\w+)@(\w+)\.(\w+)"
m = match(r, "alice@example.com")
m[1] # "alice"(第一个分组)
m[2] # "example"
m[3] # "com"
m.captures # ["alice", "example", "com"]
命名分组(Named Capture)
r = r"(?<user>\w+)@(?<domain>\w+)\.(?<tld>\w+)"
m = match(r, "bob@site.org")
m[:user] # "bob"
m["domain"] # "site"
m[:tld] # "org"
七、替换(replace)
s = "Price: $100, Tax: $15"
# 简单替换
replace(s, r"\$\d+" => "XX") # "Price: XX, Tax: XX"
# 使用捕获组
replace(s, r"\$(\d+)" => s -> "$(parse(Int, s[1]) * 2)")
# "Price: 200, Tax: 30"
# 命名分组替换
replace(s, r"\$(?<amt>\d+)" => s -> "$(s[:amt] * 10)")
# "Price: 1000, Tax: 150"
八、前向肯定查找(Lookahead)
| 语法 | 含义 |
|---|---|
(?=...) | 正向前瞻 |
(?!...) | 负向前瞻 |
# 匹配后面跟着 .com 的邮箱,但不包含 .com
r"\w+(?=\.com)"
match(r"\w+(?=\.com)", "alice@example.com") # nothing
match(r"\w+(?=\.com)", "bob@gmail.com") # nothing
# 正确示例:
s = "alice@example.com"
match(r"\w+(?=\.com)", s) # RegexMatch("example")
九、实际应用示例
1. 提取所有手机号(中国大陆)
text = """
联系人:张三,电话:138-1234-5678
李四:13912345678
王五:+86 136 9876 5432
"""
pattern = r"1[3-9]\d{9}|1[3-9]\d{2}-\d{4}-\d{4}"
phones = [m.match for m in eachmatch(pattern, text)]
# → ["138-1234-5678", "13912345678", "13698765432"]
2. 解析日志时间戳
log = "[2025-10-26 14:30:22] ERROR: Connection failed"
r = r"\[(?<date>\d{4}-\d{2}-\d{2}) (?<time>\d{2}:\d{2}:\d{2})\] (?<level>\w+): (?<msg>.*)"
m = match(r, log)
m[:date] # "2025-10-26"
m[:time] # "14:30:22"
m[:level] # "ERROR"
m[:msg] # "Connection failed"
3. 清理 HTML 标签
html = "<p>Hello <b>World</b>!</p>"
clean = replace(html, r"<[^>]*>" => "")
# → "Hello World!"
十、正则表达式速查表
| 模式 | 含义 |
|---|---|
. | 任意字符 |
^ | 行首 |
$ | 行尾 |
* | 0次或多次 |
+ | 1次或多次 |
? | 0次或1次 |
{n,m} | n到m次 |
[abc] | a或b或c |
[^abc] | 非a/b/c |
\d | 数字 |
\w | 单词字符 |
\s | 空白 |
(abc) | 分组 |
(?<name>abc) | 命名分组 |
a|b | a或b |
(?=abc) | 正向前瞻 |
十一、性能建议
| 建议 | 说明 |
|---|---|
| 提前编译正则 | const EMAIL_REGEX = r"..." |
| 避免过度嵌套 | 复杂正则变慢 |
用 occursin 快速判断 | 比 match 快 |
大文本用 eachmatch 流式处理 | 节省内存 |
const PHONE_REGEX = r"1[3-9]\d{9}"
function is_valid_phone(s)
occursin(PHONE_REGEX, s)
end
十二、小练习(立即上手)
- 匹配 IPv4 地址(如
192.168.1.1) - 提取 URL 中的协议、域名、路径
- 将
2025-10-26转为2025年10月26日 - 匹配连续重复的单词(如 “the the”)
- 实现
split函数(用正则)
答案示例
# 1. IPv4
ipv4 = r"^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$"
# 验证:all(x -> 0 ≤ parse(Int,x) ≤ 255, m.captures)
# 2. URL 解析
url = r"(?<protocol>https?)://(?<host>[^/]+)(?<path>/.*)?"
m = match(url, "https://example.com/path/to/file")
m[:protocol], m[:host], m[:path]
# 3. 日期格式化
date = "2025-10-26"
replace(date, r"(\d{4})-(\d{2})-(\d{2})" => s"\1年\2月\3日")
# 4. 重复单词
text = "this this is a a test"
[m.match for m in eachmatch(r”\b(\w+)\s+\1\b”i, text)]
# → [“this this”, “a a”] # 5. 正则 split mysplit(s, delim) = [m.match for m in eachmatch(Regex(“.*?$delim”), s)][1:end-1]
十三、调试工具
using RegexTools # 可选包:可视化正则
# 或在线:https://regex101.com (选择 PCRE)
恭喜!你已精通 Julia 正则表达式!
现在你可以:
- 轻松解析日志、CSV、HTML
- 实现数据清洗、验证
- 写出高效文本处理管道
- 构建配置解析器、爬虫
下一站推荐
| 主题 | 为什么学 |
|---|---|
CSV.jl | 真实数据导入 |
HTTP.jl + 正则 | 网页爬取 |
DataFrames | 数据清洗 |
Parsers.jl | 高性能解析 |
TextAnalysis.jl | NLP 基础 |
需要我:
- 写一个 日志分析器(提取时间、级别、消息)?
- 实现 配置文件解析器(.ini / .toml 风格)?
- 构建 邮箱验证 + 提取工具?
- 生成 正则表达式思维导图?
随时告诉我!