当前位置: 代码网 > it编程>编程语言>正则表达式 > 正则表达式常见困惑与实际操作(速查指南)

正则表达式常见困惑与实际操作(速查指南)

2026年08月29日 正则表达式 我要评论
一、规则在线测试页面1. 基础元字符字符含义示例.匹配除换行符外任意字符a.c → abc[]字符集合[ae] → apple, egg[^]否定字符集[^ae] → a

一、规则

在线测试页面

1. 基础元字符

字符含义示例
.匹配除换行符外任意字符a.c → abc
[]字符集合[ae]apple, egg
[^]否定字符集[^ae] → apple, egg
*匹配0次或多次zo*z, zo, zoo
+匹配1次或多次zo+ → z, zo, zoo
?匹配0次或1次zo?z, zo, zoo
{n}匹配n次o{2} → food
{n,}至少匹配n次o{2,} → foood
{n,m}匹配n到m次o{2,3} → foood
^字符串开头^aapple
$字符串结尾e$ → apple
|或运算符(z|f)oodzood, food
\转义字符\. → a.b

2. 分组与引用

语法功能示例
( )捕获分组(\d{4})2023-01
\n引用第n个分组^(abc)\1$abcabc
(?<name>)命名分组(?<year>\d{4})

3. 字符集合简写

字符等价于含义
\d[0-9]数字字符
\w[a-za-z0-9_]单词字符(字母、数字、下划线)
\s[ \t\n\r\f\v]空白字符(空格、制表符等)
\b-单词边界
\n-换行符
\t-制表符
\r-回车符

4. 反向字符类

字符等价于含义
\d[^0-9]非数字字符
\w[^a-za-z0-9_]非单词字符
\s[^ \t\n\r\f\v]非空白字符
\b-非单词边界

5. 特殊字符类

字符含义
\f换页符
\v垂直制表符
\0空字符
\cx控制字符(如 \cm 匹配回车)
\xhh十六进制值 hh 表示的字符
\uhhhhunicode 字符

6. 零宽断言

语法名称示例
(?=...)正向先行断言\d+(?=px) → 12px, 15px
(?!...)负向先行断言\d{3}(?!px) → 123px, 456em
(?<=...)正向后行断言(?<=\$)\d+ → **$**100
(?<!...)负向后行断言(?<!\$)\d+ → 100, €200

7. 标志符

标志功能
g全局搜索
i不区分大小写
m多行模式

8. 常用正则模式

用途正则表达式
用户名/^[a-z0-9_-]{3,16}$/
电子邮箱/^[\w\.-]+@[\w\.-]+\.[a-z]{2,6}$/
url/^(https?:\/\/)?[\w\.-]+\.[a-z]{2,6}\/?[\w\/\.-]*$/
ipv4地址/((25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)\.){3}(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)/
日期/^(0?[1-9]|1[0-2])[\/\-\.](0?[1-9]|[12]\d|3[01])[\/\-\.]\d{4}$/
中文姓名/^[\u4e00-\u9fa5]{2,4}$/
手机号码/^1[3-9]\d{9}$/
身份证号/^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dx]$/
信用卡号/^\d{4}[- ]?\d{4}[- ]?\d{4}[- ]?\d{4}$/
十六进制颜色值/^#?([a-f0-9]{6}|[a-f0-9]{3})$/i
html标签/^<([a-z]+)([^<]+)*(?:\/>|>(.*?)<\/\1>)$/
文件路径/^(\/\w+)+\/?(\w+\.\w+)?$/
金额(两位小数)/^\d+(\.\d{1,2})?$/
mac地址/^([0-9a-fa-f]{2}[:-]){5}([0-9a-fa-f]{2})$/
车牌号(中国)/^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼][a-z][a-z0-9]{5}$/

二、常见困惑

1.(z|f)和[z|f]的区别

表达式类型匹配内容示例匹配结果
(z|f)分组匹配完整的 zf(z|f)oodzood, food
[z|f]字符集匹配单个字符 zf|[z|f]z, f, |
  • 关键区别:
  1. (z|f)选择模式,匹配整个 zf
  2. [z|f]字符集合,匹配方括号内的任意单个字符(包括字面量 |
  • 常见错误示例:
[z|f]ood  # 会意外匹配 "|ood"
(z|f)ood   # 正确匹配 "zood" 或 "food" 或 “|ood”

2. 断言与捕获的区别

  • 断言(零宽断言)
语法名称特点示例
(?=...)正向先行断言不消耗字符,只检查右侧\d+(?=px) → 匹配"12"(在"12px"中)
(?!...)负向先行断言不包含在匹配结果中\d{3}(?!px) → 匹配"456"(当后面不是"px"时)
(?<=...)正向后行断言检查左侧但不捕获(?<=\$)\d+ → 匹配"100"(当前面是$时)
(?<!...)负向后行断言不消耗左侧字符(?<!\$)\d+ → 匹配"200"(当前面不是$时)
  • 捕获组
语法特点示例
(...)消耗字符并存储匹配内容(\d{4})-(\d{2}) → 捕获"2023"和"01"(从"2023-01"中)
(?:...)不捕获的纯分组(?:\d{3})-(\d{4}) → 只捕获后4位数字
  • 核心区别

    1. 内存消耗

      • 断言:不占用匹配结果(零宽度)
      • 捕获:会存储匹配内容
    2. 应用场景

	   // 断言(提取价格数字但不包含货币符号)
	   "price: $100".match(/(?<=\$)\d+/); // → ["100"]
	   
	   // 捕获(同时获取货币符号和数字)
	   "price: $100".match(/(\$)(\d+)/);  // → ["$100", "$", "100"]
		[0]	"$100"	完整匹配的字符串
		[1]	"$"	第一个捕获组 (\$) 匹配的内容
		[2]	"100"	第二个捕获组 (\d+) 匹配的内容

2. 断言怎么用

正向先行断言 (?=…)

  • 示例:匹配后面跟着句号的数字
    \d(?=.)
    示例文本:1. 5. 7
    匹配结果(两个):(1, 5)

负向先行断言 (?!..)

  • 示例:匹配后面不跟着句号的数字
    \d(?!\.)
    示例文本:1. 5 7
    匹配结果(两个):(5, 7)

正向后行断言 (?<=…)

  • 示例:匹配前面是字母的数字
    (?<=[a-za-z])\d
    示例文本:a1 b2 3c
    匹配结果(两个):(1, 2)

负向后行断言 (?<!..)

  • 示例:匹配前面不是字母的数字
    (?<![a-za-z])\d
    示例文本:1a2b 3
    匹配结果(两个):(1, 3)

单词边界 (b)

  • 示例:匹配独立的单词"cat"
    \bcat\b
    示例文本:cat category a cat
    匹配结果(两个):(cat, cat)

行首/行尾 (^ 和 $)

  • 示例:匹配以 “hello” 开头的行
    ^hello
    示例文本:hello world hello there
    匹配结果:hello

三、实际操作

1. vscode 正则替换

  1. 所有注释加一个空格
//heeeeellll ---> // heeeeellll
#heeeeellll ---> # heeeeellll  
(?<!:)(//)(\s.*|[\u4e00-\u9fff].*)
(#)(\s.*|[\u4e00-\u9fff].*)
$1 $2
  1. function 转 const
#查找:function\s(\w+)\((.*)\)
#替换:const $1 = ($2)  => 

结果:
function screencheck()
const screencheck = ()  =>
  1. as
查找:<([\w|.]+)>([\w|.]+)
替换:$2 as $1

结果:
controller as functioncontroller
<functioncontroller>controller

2. c++用法

1. regex_match 整个字符串 要求完全匹配!

std::cmatch m;
auto ret = std::regex_match("<xml>value</xml>", m, std::regex("<(.*)>(.*)</xml>"));
if (ret)
{
	std::cout << m.str() << std::endl;
	std::cout << m.length() << std::endl;
	std::cout << m.position() << std::endl;
}

// 遍历匹配内容
for (auto i = 0; i < m.size(); ++i)
{
	// 两种方式都可以 输出括号()捕获的子串
	std::cout << m[i].str() << " " << m.str(i) << std::endl;
}

-------------------------------
<xml>value</xml>
16
0

<xml>value</xml> <xml>value</xml>
xml xml
value value
xml xml
-------------------------------

2. regex_search 只要字符串中有目标出现就会返回,而非完全「匹配」

std::cmatch m;
auto ret = std::regex_match("123<xml>value</xml>456", m, std::regex("<(.*)>(.*)</xml>"));
if (ret)
{
	for (auto& elem : m)
		std::cout << elem << std::endl;
}
std::cout << "prefix:" << m.prefix() << std::endl;
std::cout << "suffix:" << m.suffix() << std::endl;

-------------------------------
<xml>value</xml>
xml
value
xml

prefix:123
suffix:456
-------------------------------

// 注意:如果有多个符合的内容
std::regex reg("<(.*)>(.*)</(.*)>");
std::string content("123<xml>value</xml>456<widget>center</widget>hahaha<vertical>window</vertical>the end");
std::smatch m;
auto pos = content.cbegin();
auto end = content.cend();
for (; std::regex_search(pos, end, m, reg); pos = m.suffix().first)
{
	std::cout << "----------------" << std::endl;
	std::cout << m.str() << std::endl;
	std::cout << m.str(1) << std::endl;
	std::cout << m.str(2) << std::endl;
	std::cout << m.str(3) << std::endl;
}

-------------------------------
<xml>value</xml>
xml
value
xml
----------------
<widget>center</widget>
widget
center
widget
----------------
<vertical>window</vertical>
vertical
window
vertical
-------------------------------

3. regex_replace 在整个字符串中替换符合正则表达式规则的字段

string str = "hello_2018!";	

regex pattern("hello");	
cout << regex_replace(str, pattern, "") << endl;	//输出:_2018,将hello替换为""
cout << regex_replace(str, pattern, "hi") << endl;	//输出:hi_2018,将hello替换为hi

regex pattern2("(.{3})(.{2})_(\\d{4})");				//匹配3个任意字符+2个任意字符+下划线+4个数字
cout << regex_replace(str, pattern2, "$1$3") << endl;	//输出:hel2018,将字符串替换为第一个和第三个表达式匹配的内容
cout << regex_replace(str, pattern2, "$1$3$2") << endl;	//输出:hel2018lo,交换位置顺序

3. js 用法

var str = "aaabbbcccaaabbbccc";

// match
var res = str.match(/aaa/); // 没有使用g选项
输出:[ 'aaa', index: 0, input: 'aaabbbcccaaabbbccc' ]

var res = str.match(/aaa/g); // g(全局匹配) 使用g选项,全局匹配
输出:[ 'aaa', 'aaa' ]

// exec
var res =/aaa/.exec(str);
输出:[ 'aaa', index: 0, input: 'aaabbbcccaaabbbccc' ]

var res =/aaa/g.exec(str);
输出:[ 'aaa', index: 0, input: 'aaabbbcccaaabbbccc' ]

var res = /ccc([0-9]+)aaa/.exec("aaabbbccc1234aaabbbcccaaabbbccc5678aaabbbccc");
输出:[ 'ccc1234aaa', '1234', index: 6, input: 'aaabbbccc1234aaabbbccc' ]

var res = /ccc([0-9]+)aaa/g.exec("aaabbbccc1234aaabbbcccaaabbbccc5678aaabbbccc");
"ttt.md".match(/(.*).md/)[1]; //返回匹配数组

输出:[ 'ccc1234aaa', '1234', index: 6, input: 'aaabbbccc1234aaabbbcccaaabbbccc5678aaabbbccc' ][ 'ccc5678aaa', '5678', index: 28, input: 'aaabbbccc1234aaabbbcccaaabbbccc5678aaabbbccc' ]

/.*\.md$/g.exec("ttt.md")[1]; //返回匹配数组

// search
var res = "aaabbbcccaaabbbccc".search(/ccc/)
输出: 6

var res = "aaabbbcccaaabbbccc".replace(/aaa/, '111′);
输出: 111bbbcccaaabbbccc

// split
var res = "aaa,bbb,ccc".split(/,/)
输出: [ 'aaa', 'bbb', 'ccc' ]
var res = "aaa,bbb:ccc@ddd#eee".split(/[,:@#]/)
输出: [ 'aaa', 'bbb', 'ccc', 'ddd', 'eee' ]
var res = "aaa,bbb:ccc@ddd#eee".split(/[,:@#]/,3)
输出: [ 'aaa', 'bbb', 'ccc' ]

4. python 用法

import re

# 1. 邮箱验证
emails = ["test@example.com", "invalid@.com", "name@domain.org"]
pattern = r'^[\w\.-]+@[\w\.-]+\.[a-za-z]{2,6}$'
for email in emails:
    if re.match(pattern, email):
        print(f"✅ 有效邮箱: {email}")
    else:
        print(f"❌ 无效邮箱: {email}")

# 2. 提取日期信息
text = "会议时间: 2023-08-15, 截止日期: 2024-01-20"
dates = re.findall(r'(\d{4})-(\d{2})-(\d{2})', text)
for year, month, day in dates:
    print(f"📅 日期: {year}年{month}月{day}日")

# 3. 替换敏感词
content = "这个价格是500元,但vip价格是400元"
sanitized = re.sub(r'vip价格', '***', content)
print(f"🔒 脱敏内容: {sanitized}")

# 4. 分割复杂字符串
data = "alice:30;bob:25;charlie:28"
users = re.split(r'[;:]', data)
print("👥 用户数据:", users)

# 5. 提取html标签内容
html = "<div>标题</div><p>正文内容</p>"
tags = re.findall(r'<([a-z]+)>(.*?)</\1>', html)
for tag, content in tags:
    print(f"🏷️ {tag}标签内容: {content}")

# 6. 密码强度验证
passwords = ["pass123!", "weak", "strongpwd#2023"]
for pwd in passwords:
    if re.match(r'^(?=.*[a-z])(?=.*[a-z])(?=.*\d)(?=.*[!@#$%^&*]).{8,}$', pwd):
        print(f"🔐 强密码: {pwd}")
    else:
        print(f"⚠️ 弱密码: {pwd}")

# 7. 提取中文内容
text = "python3.8发布 2020年10月,支持中文变量名=很棒"
chinese = re.findall(r'[\u4e00-\u9fa5]+', text)
print("🇨🇳 中文内容:", chinese)

# 8. 匹配ip地址
ips = ["192.168.1.1", "256.0.0.1", "127.0.0.1"]
pattern = r'^((25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)\.){3}(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)$'
for ip in ips:
    if re.match(pattern, ip):
        print(f"🌐 有效ip: {ip}")
    else:
        print(f"🚫 无效ip: {ip}")

# 9. 多行模式匹配
text = """标题
第一行
最后一行"""
match = re.search(r'^最后一行$', text, re.multiline)
if match:
    print(f"📝 找到结尾行: '{match.group()}'")

# 10. 预编译正则提高性能
pattern = re.compile(r'\b\w{4}\b')  # 匹配4字母单词
text = "this is sample text with some four letter words"
matches = pattern.findall(text)
print("🔤 4字母单词:", matches)

总结 

到此这篇关于正则表达式常见困惑与实际操作的文章就介绍到这了,更多相关正则表达式速查指南内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com