正则表达式
系列【正则表达式】──用一个表达式搜索不同日期
上一篇《系列【正则表达式】──AI 时代依然实用的知识》介绍了正则表达式最基本的思路:不是搜索某一个固定字符串,而是按照“文字模式”来搜索。
这一次,我们再往前走一步。
假设文档中出现了下面这些日期:
年、月、日都不一样。
如果使用普通搜索,就需要分别搜索每一个日期;但使用正则表达式,就可以用一个表达式一次把它们全部找出来。
这篇文章不会一开始就给出最终答案让大家死记硬背,而是继续使用上一篇学过的内容,一小步一小步把表达式搭起来。
先搜索“年”
上一篇已经介绍过,如果要搜索“4 位数字+年”,可以写成:
\d{4}年
拆开来看:
- \d = 1 个数字
- {4} = 前面的内容恰好重复 4 次
年= 字符“年”
用这个表达式搜索刚才的示例,会匹配下面这些部分:
到这里基本上还是上一篇的复习。
接下来,把“月”也加进去。
把“月”加上去
月份可能写成:
9月
也可能写成:
12月
也就是说,数字可能是 1 位,也可能是 2 位。
上一篇介绍过,如果要表示“数字出现 1 次以上”,可以写成:
\d+
因此,我们直接把它接到刚才的表达式后面:
\d{4}年\d+月
这一次,匹配到的范围会更长一些:
现在已经越来越接近完整日期了。
再把“日”加进去
“日”也一样,可能是:
1日
也可能是:
31日
所以,再添加一个 \d+:
\d{4}年\d+月\d+日
这样就可以把整个日期一次匹配出来。
其实到这里,我们已经完成了这篇文章最初的目标。
这里有一个很重要的概念值得记住:
对于同一个搜索目标,正则表达式不一定只有一种正确写法。
以这次的日期为例:
\d{4}年\d+月\d+日
本身就是一个完全可用的答案。
为了搜索同一类字符串,经常可以写出不同的正则表达式。有的范围更宽,有的限制更严格;有的更短,有的虽然更长,却能把意图表达得更清楚。
关键不是找到“唯一正确的公式”,而是能不能把自己真正想找的文字模式表达出来。
在这个基础上,我们再进一步,把月和日写得更具体一些。
更准确地表示“月”和“日”的位数
实际日期可能写成:
2026年9月1日2026年09月01日2025年12月31日
也就是说,月和日既可能是 1 位数,也可能是 2 位数。
如果把搜索条件说得更准确一些,我们真正想表达的是:
“月和日分别由 1 位或 2 位数字组成。”
如果写成:
\d{2}
那么只能匹配 09、31 这样的两位数,却匹配不到 9 或 1。
这时就可以使用今天要介绍的新写法:
{1,2}
{1,2}——重复 1 次到 2 次
上一篇介绍过:
{4}
表示“前面的内容恰好重复 4 次”。
同样地,
{1,2}
表示:
前面的内容至少出现 1 次,最多出现 2 次。
因此:
\d{1,2}
就是:
1 位或 2 位数字。
把它放到月和日的位置,就得到:
\d{4}年\d{1,2}月\d{1,2}日
拆开来看:
| 表达式 | 含义 |
|---|---|
| \d{4} | 4 位数字 |
年 | 字符“年” |
| \d{1,2} | 1 位或 2 位数字 |
月 | 字符“月” |
| \d{1,2} | 1 位或 2 位数字 |
日 | 字符“日” |
也就是:
4 位数字+年+1~2 位数字+月+1~2 位数字+日。
图 1 想找的日期各部分,与 \d{4}年\d{1,2}月\d{1,2}日 各组成部分之间的对应关系。
现在再比较一下:
\d{4}年\d+月\d+日
和
\d{4}年\d{1,2}月\d{1,2}日
对于本文列出的这些日期,两种写法都可以匹配。
第二种只是多表达了一个条件:月和日分别包含 1~2 位数字。
并不是第一种错、第二种才对。两种都可以是正确答案。
条件要写得多细,取决于实际数据和搜索目的。使用正则表达式时,经常可以先写出一个“能完成任务”的版本,再根据需要缩小范围,或者反过来把表达式简化。
匹配到“日期格式”,不代表它真的是有效日期
还有一点需要注意。
刚才写的:
\d{4}年\d{1,2}月\d{1,2}日
也会匹配:
2026年99月99日
显然,99 月和 99 日都不存在。
原因很简单:正则表达式看到的只是文字模式。
我们设定的条件只是:
4 位数字后面是“年”,接着是 1~2 位数字和“月”,最后再接 1~2 位数字和“日”
它并不知道一年有多少个月,也不知道 2 月到底有多少天。
当然,我们可以继续增加条件,让表达式限制得更严格;但表达式也会迅速变复杂。
在翻译或 QA 工作中,很多时候先把可能的候选项全部找出来,再人工确认,就已经足够。
所以真正应该考虑的不是“能不能写出最严密的正则表达式”,而是:这次任务到底需要多精确?
在翻译和 QA 中有什么用?
这次的表达式非常简单,但在长文档或大型项目中其实很实用。
例如,需要检查文档中的日期格式是否统一时,可以用一个正则表达式一次找出多个不同日期,而不必事先知道每一个具体日期。
在支持正则表达式的搜索或筛选功能中,也可以借此快速缩小需要检查的范围。
memoQ 的查找和替换,以及翻译编辑器中的筛选等功能,也支持正则表达式。
这也是正则表达式和翻译、QA 工作很搭的原因之一:我们可以描述“想找的文字长什么样”,而不需要提前知道它的完整内容。
还是不用背最终公式
如果只看:
\d{4}年\d{1,2}月\d{1,2}日
一开始可能会觉得有点复杂。
但回头看一下这篇文章真正做了什么:
我们先从:
\d{4}年
开始,再加上月份:
\d{4}年\d+月
然后加上“日”:
\d{4}年\d+月\d+日
到这里,搜索其实已经可以正常完成。
之后只是因为我们还想把“月和日都是 1~2 位”这个条件明确写出来,所以改成:
\d{4}年\d{1,2}月\d{1,2}日
一步一步拆开来看,并没有做什么特别复杂的事情。
而且,也不需要把其中某一种写法当成唯一的“标准答案”背下来。
同一个搜索目标,本来就可能有多种正则表达式写法。
有时简单、宽松一点的表达式已经够用;有时则需要把条件写得更细。
真正重要的是,把想搜索的字符串拆成小的组成部分,再根据实际任务把这些部分组合成合适的模式。
下一篇:从搜索进入“替换”
这一次,我们学会了如何一次搜索不同的年月日。
下一篇会再进一步,从“搜索”进入“替换”。
例如,我们可以把:
2026年9月1日
重新排列成:
9/1/2026
或其他顺序。
要做到这一点,就需要让正则表达式先“记住”年、月、日分别是哪一部分,然后在替换时把这些部分重新拿出来排列。
下一篇就会介绍这个非常实用的功能:捕获组(capture groups)。