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

PHP preg_replace处理各类年份格式(YYYY、YYYY-YYYY、YYYY - YYYY)

Alright, let's work through this regex conflict issue together. The main problem here is that your single-year pattern is catching parts of year ranges because it's being evaluated first. The fix is to prioritize matching the longer, more specific range patterns first, then target only standalone single years that aren't part of any range.

Solution Approach

We'll use a sequential preg_replace workflow: first handle both types of year ranges, then match only single years that aren't part of a range. This avoids overlapping matches and ensures each format gets processed correctly.

Step 1: Define Targeted Regex Patterns

Here are the refined patterns, designed to avoid conflicts and accurately target each format:

1. Spaced Year Range (YYYY - YYYY)

'/(\b19[5-9]\d|20[01]\d|2020) - (\b19[5-9]\d|20[01]\d|2020)\b/'
  • Matches valid 1950-2020 years on both sides of a spaced hyphen
  • Uses \b word boundaries to prevent partial matches (e.g., ignoring 19500 - 2021)

2. Unspaced Year Range (YYYY-YYYY)

'/(\b19[5-9]\d|20[01]\d|2020)-(\b19[5-9]\d|20[01]\d|2020)\b/'
  • Identical to the spaced range pattern, but targets hyphens without surrounding spaces

3. Standalone Single Year (YYYY)

'/(\b19[5-9]\d|20[01]\d|2020)\b(?!\s*-|\s*-\s*)/'
  • Matches valid single years
  • The negative lookahead (?!\s*-|\s*-\s*) ensures the year isn't followed by a hyphen (with or without spaces), so it won't accidentally match the start of a range

Step 2: PHP Implementation Example

We'll chain the preg_replace calls to process ranges first, then single years. Adjust the replacement HTML to match your exact formatting needs (e.g., <br> tags, styled containers):

$input = "Sample text: 2014, 2000-2010, 1995 - 2005, and 1987 are all here.";

// Process spaced year ranges first
$output = preg_replace(
    '/(\b19[5-9]\d|20[01]\d|2020) - (\b19[5-9]\d|20[01]\d|2020)\b/',
    '<br><div class="year-range">Range: $1 - $2</div>',
    $input
);

// Next process unspaced year ranges
$output = preg_replace(
    '/(\b19[5-9]\d|20[01]\d|2020)-(\b19[5-9]\d|20[01]\d|2020)\b/',
    '<br><div class="year-range">Range: $1 - $2</div>',
    $output
);

// Finally process standalone single years
$output = preg_replace(
    '/(\b19[5-9]\d|20[01]\d|2020)\b(?!\s*-|\s*-\s*)/',
    '<br><div class="single-year">Year: $1</div>',
    $output
);

echo $output;

Step 3: Expected Output

For the sample input above, the formatted output will be:

Sample text: <br><div class="single-year">Year: 2014</div>, <br><div class="year-range">Range: 2000 - 2010</div>, <br><div class="year-range">Range: 1995 - 2005</div>, and <br><div class="single-year">Year: 1987</div> are all here.

Key Fixes Explained

  • Priority Order: By processing ranges first, we ensure the single-year pattern can't match parts of a range (like 2000 in 2000-2010).
  • Negative Lookahead: The single-year pattern skips any year that's about to be part of a range, eliminating false matches.
  • Word Boundaries: \b guarantees we only match full 4-digit years, not partial numbers embedded in other text.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:21:24