第1章:正则表达式与数据结构——用正则解析JSON、XML、YAML及自定义格式
各位同学,今天我们来聊一个很实在的话题——用正则表达式解析各种数据格式。
说实话,我刚开始做嵌入式开发那会儿,遇到JSON、XML这些格式,第一反应就是去找现成的解析库。后来有一次在资源受限的MCU上做项目,库太大塞不进去,逼得我手写解析器。嗯,就是那次经历让我发现——正则表达式在某些场景下,比完整解析库更灵活、更轻量。
当然,我不是说让你用正则去替代成熟的解析器。但当你需要快速提取数据、做日志分析、或者写一次性脚本时,正则绝对是一把利器。
1.1 为什么用正则解析结构化数据?
你想想看,JSON、XML、YAML这些格式,本质上都是文本。既然是文本,正则就能派上用场。
我个人的习惯是:
- 生产环境:用成熟的解析库(如cJSON、libxml2)
- 调试/日志分析:用正则快速提取关键字段
- 资源受限环境:用正则实现轻量级解析器
核心原则:正则适合提取数据,不适合验证完整语法。别拿正则去校验JSON是否合法——那是解析器干的事。
1.2 用正则解析JSON
JSON的结构其实很简单:键值对,用花括号包裹。我们最常见的需求是提取某个字段的值。
举个例子,假设有这段JSON:
{
"name": "张三",
"age": 28,
"city": "北京"
}
我想提取name字段的值。正则怎么写?
"name"\s*:\s*"([^"]*)"
解释一下:
"name":匹配字段名\s*:\s*:匹配冒号及可能的空格"([^"]*)":匹配双引号内的值,用捕获组提取
我在项目中遇到过一个问题:JSON里的字符串值可能包含转义引号,比如"say: \"hello\""。这时候上面的正则就失效了。改进版:
"name"\s*:\s*"((?:[^"\\]|\\.)*)"
这个正则考虑了转义字符,能正确匹配带引号的值。
小技巧:如果JSON是压缩格式(没有空格),去掉\s*即可。我经常写两个版本,一个给格式化JSON用,一个给压缩JSON用。
1.3 用正则解析XML
XML比JSON麻烦一点,因为有嵌套标签和属性。但如果我们只是提取标签内的文本,正则依然好用。
比如这段XML:
<person>
<name>李四</name>
<age>32</age>
</person>
提取name标签内容的正则:
<name>(.*?)</name>
这里用了.*?(非贪婪匹配),确保只匹配到第一个</name>就停下。
如果要提取属性值呢?比如:
<person id="123">
提取id属性:
id\s*=\s*"([^"]*)"
曾经踩过的坑:XML里可能有命名空间,比如<ns:name>。我一开始没注意,写死了标签名,结果解析全失败。后来改成<[^:]*:name>(.*?)</[^:]*:name>才搞定。
1.4 用正则解析YAML
YAML的语法更自由,缩进敏感。但正则依然能处理简单的键值对。
比如:
name: 王五
age: 25
city: 上海
提取name值的正则:
^name:\s*(.*)$
注意这里用了^和$锚定行首行尾,因为YAML是逐行解析的。
YAML还支持列表:
hobbies:
- 读书
- 游泳
提取列表项:
^\s*-\s*(.*)$
个人经验:YAML的嵌套结构用正则解析很吃力。我一般只用来提取顶层键值对,深层嵌套还是交给解析库。说白了,正则适合浅层提取。
1.5 用正则解析自定义格式
这才是正则真正的用武之地。很多老系统、日志文件、配置文件,用的都是非标准格式。这时候解析库帮不上忙,正则就是你的瑞士军刀。
举个例子,我曾经处理过这样的日志:
[2024-01-15 10:30:45] [INFO] 用户登录成功 - user_id=12345, ip=192.168.1.1
提取时间、级别、用户ID和IP:
\[(.*?)\]\s*\[(.*?)\]\s*.*?user_id=(\d+),\s*ip=([0-9.]+)
这个正则一次提取4个字段,效率很高。
再比如,自定义配置文件:
# 数据库配置
DB_HOST = localhost
DB_PORT = 3306
DB_USER = root
提取键值对(忽略注释):
^\s*([A-Z_]+)\s*=\s*(.*)$
建议:写自定义格式的正则时,先写注释说明每一部分匹配什么。不然过两周你自己都看不懂。我吃过这个亏。
1.6 知识体系总览
下面这张图总结了本章的核心逻辑:
1.7 实战建议与避坑指南
最后,分享几条我这些年总结的经验:
- 先写测试用例:写正则前,先准备好输入和期望输出。我每次都是先写测试,再写正则。
- 注意贪婪与非贪婪:默认是贪婪匹配,容易匹配过多。用
.*?代替.*能避免很多问题。 - 考虑边界情况:空值、特殊字符、换行符——这些最容易翻车。
- 性能问题:复杂的正则回溯可能很慢。如果数据量大,考虑分段解析。
- 不要过度使用:如果格式嵌套超过3层,或者需要验证语法正确性,请用解析库。
我曾经犯过的错:有一次用正则解析嵌套JSON,写了100多字符的正则,结果一跑就栈溢出。后来老老实实改成逐层解析,代码反而更清晰。记住:正则不是万能的。
好了,这一章就到这里。正则解析数据格式,说白了就是用模式匹配去提取你关心的信息。掌握好这个思路,后面遇到什么格式都不慌。
公众号:蓝海资料掘金营,微信 deep3321