You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP正则表达式优化:大篇幅学生作文中特定格式日期匹配需求

搞定PHP正则匹配作文中的特定日期格式

没问题,针对你需要从学生作文里匹配特定格式日期的需求,我整理了一套精准的正则方案,覆盖你提到的所有格式,同时支持()和[]两种包裹方式,还能处理大小写问题。

正则表达式解析

先直接上最终的正则(带注释版方便你理解):

/(?:\[|\()                    # 匹配开头的[或(,非捕获分组避免冗余捕获
  (?:
    (?:jan(?:uary)?|feb(?:ruary)?|mar(?:ch)?|apr(?:il)?|may|jun(?:e)?|jul(?:y)?|aug(?:ust)?|sep(?:tember)?|oct(?:ober)?|nov(?:ember)?|dec(?:ember)?)
    -\d{4}                   # 匹配「月份缩写/全称-年份」格式
    |
    \d{4}-
    (?:jan(?:uary)?|feb(?:ruary)?|mar(?:ch)?|apr(?:il)?|may|jun(?:e)?|jul(?:y)?|aug(?:ust)?|sep(?:tember)?|oct(?:ober)?|nov(?:ember)?|dec(?:ember)?)
                             # 匹配「年份-月份缩写/全称」格式
    |
    \d{4}                    # 匹配纯四位年份格式
  )
(?:\]|\))/ix                 # 匹配结尾的]或),x修饰符允许正则换行注释,i修饰符忽略大小写

如果不需要注释,直接用精简版:

/(?:\[|\()(?:(?:jan(?:uary)?|feb(?:ruary)?|mar(?:ch)?|apr(?:il)?|may|jun(?:e)?|jul(?:y)?|aug(?:ust)?|sep(?:tember)?|oct(?:ober)?|nov(?:ember)?|dec(?:ember)?)-\d{4}|\d{4}-(?:jan(?:uary)?|feb(?:ruary)?|mar(?:ch)?|apr(?:il)?|may|jun(?:e)?|jul(?:y)?|aug(?:ust)?|sep(?:tember)?|oct(?:ober)?|nov(?:ember)?|dec(ember)?)|\d{4})(?:\]|\))/i

关键特性

  • 大小写兼容:通过i修饰符,不管是nov还是NOV、November都能匹配
  • 双包裹支持:同时处理()和[]包裹的日期
  • 全格式覆盖:完美匹配你列出的5种日期格式:纯年份、月份缩写/全称-年份、年份-月份缩写/全称
  • 非捕获分组优化:用(?:...)减少不必要的捕获组,让匹配结果更整洁

PHP代码示例

因为是大篇幅作文,大概率需要匹配所有符合条件的日期,所以用preg_match_all更合适:

// 模拟学生提交的作文内容
$essayContent = "在1990年的秋天,作者提到了(1994)的重要事件,还有[nov-1994]的旅行经历,(november-1994)的会议记录,以及[1994-nov]的日记片段,最后提到(1994-november)的毕业仪式。无关内容比如(abc123)不会被匹配。";

// 使用精简版正则
$datePattern = '/(?:\[|\()(?:(?:jan(?:uary)?|feb(?:ruary)?|mar(?:ch)?|apr(?:il)?|may|jun(?:e)?|jul(?:y)?|aug(?:ust)?|sep(?:tember)?|oct(?:ober)?|nov(?:ember)?|dec(ember)?)-\d{4}|\d{4}-(?:jan(?:uary)?|feb(?:ruary)?|mar(?:ch)?|apr(?:il)?|may|jun(?:e)?|jul(?:y)?|aug(?:ust)?|sep(?:tember)?|oct(?:ober)?|nov(ember)?|dec(ember)?)|\d{4})(?:\]|\))/i';

// 匹配所有符合条件的日期
preg_match_all($datePattern, $essayContent, $matchedDates);

// 输出匹配结果
echo "匹配到的日期:\n";
print_r($matchedDates[0]);

运行后会输出:

匹配到的日期:
Array
(
    [0] => (1994)
    [1] => [nov-1994]
    [2] => (november-1994)
    [3] => [1994-nov]
    [4] => (1994-november)
)

进阶需求:提取不带包裹符号的日期

如果你只需要里面的日期内容(比如去掉()或[]),只需调整正则,把内部日期部分用捕获分组:

/(?:\[|\()((?:jan(?:uary)?|feb(?:ruary)?|mar(?:ch)?|apr(?:il)?|may|jun(?:e)?|jul(?:y)?|aug(?:ust)?|sep(?:tember)?|oct(?:ober)?|nov(ember)?|dec(ember)?)-\d{4}|\d{4}-(?:jan(uary)?|feb(ruary)?|mar(ch)?|apr(il)?|may|jun(e)?|jul(y)?|aug(ust)?|sep(tember)?|oct(ober)?|nov(ember)?|dec(ember)?)|\d{4})(?:\]|\))/i

此时$matchedDates[1]就是不带包裹符号的日期数组:

Array
(
    [0] => 1994
    [1] => nov-1994
    [2] => november-1994
    [3] => 1994-nov
    [4] => 1994-november
)

内容的提问来源于stack exchange,提问作者user3393366

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:16:06