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

PCRE2正则优化:将引号/无引号src值捕获至同一分组

正则优化:统一捕获img标签的src属性值(PCRE2/PHP >=7.3)

环境与需求

正则环境:PCRE2(PHP >= 7.3)

现有一段包含多个<img>标签的多行字符串,需实现以下正则捕获:

  • 捕获所有包含src属性的完整<img>标签;
  • 捕获上述src属性的属性值。

src属性格式规则:

  • 可使用双引号、单引号包裹,或无引号包裹;
  • 带引号时,属性值内不得包含对应引号;
  • 无引号时,属性值内不得包含空白字符或>。

当前问题

现有正则已实现基本匹配,但带引号的src值被捕获至$matches[2],无引号的被捕获至$matches[3],需要手动复制数据到同一分组,现需优化正则,让两类src值直接捕获到同一个分组中。

原实现代码

$code = <<<EOD
1. <img width src = one height>
2. <notAtStart><img src=two height>
3. NotAtAll
4. <img width src="three"><notAtEnd>
5. <notAtStart><img src = 'four' /><notAtEnd>
6. <img src =five><test>
7. <img WithoutSrc>
EOD;

$regex='/(<IMG(?=\s).*\sSRC\s*=\s*
    (?(?=["\'])
        .(.+?) ["\'] 
     |         
        (.+?) [\s>]
    )
    (?(?<!>).*?>)
)/ix';

preg_match_all($regex, $code, $matches);
echo PHP_EOL . "Matches:";
// print all groups:
print_r($matches);

// copy matches captures in $matches[2] to $matches[3]
foreach($matches[2] as $a=>$b) 
    if ($b != "")
        $matches[3][$a] = $b;

// print the whole captured img tags:
print_r($matches[1]);
// print just the captured paths:
print_r($matches[3]);

原输出

Matches:Array
(
    [0] => Array
        (
            [0] => <img width src = one height>
            [1] => <img src=two height>
            [2] => <img width src="three">
            [3] => <img src = 'four' />
            [4] => <img src =five>
        )

    [1] => Array
        (
            [0] => <img width src = one height>
            [1] => <img src=two height>
            [2] => <img width src="three">
            [3] => <img src = 'four' />
            [4] => <img src =five>
        )

    [2] => Array
        (
            [0] => 
            [1] => 
            [2] => three
            [3] => four
            [4] => 
        )

    [3] => Array
        (
            [0] => one
            [1] => two
            [2] => 
            [3] => 
            [4] => five
        )

)
Array
(
    [0] => <img width src = one height>
    [1] => <img src=two height>
    [2] => <img width src="three">
    [3] => <img src = 'four' />
    [4] => <img src =five>
)
Array
(
    [0] => one
    [1] => two
    [2] => three
    [3] => four
    [4] => five
)

优化方案

使用PCRE2支持的分支重置组((?|...)),这个语法可以让不同分支中的捕获组复用同一个编号,从而把带引号和无引号的src值统一捕获到同一个分组里。

优化后的正则表达式:

$regex='/(<IMG(?=\s).*\sSRC\s*=\s*
    (?|
        ["\'](.+?)["\'] 
     |         
        (.+?)[\s>]
    )
    (?(?<!>).*?>)
)/ix';

优化后代码与输出

$code = <<<EOD
1. <img width src = one height>
2. <notAtStart><img src=two height>
3. NotAtAll
4. <img width src="three"><notAtEnd>
5. <notAtStart><img src = 'four' /><notAtEnd>
6. <img src =five><test>
7. <img WithoutSrc>
EOD;

$regex='/(<IMG(?=\s).*\sSRC\s*=\s*
    (?|
        ["\'](.+?)["\'] 
     |         
        (.+?)[\s>]
    )
    (?(?<!>).*?>)
)/ix';

preg_match_all($regex, $code, $matches);
echo PHP_EOL . "Matches:";
print_r($matches);

// 直接获取统一的src值分组,无需手动复制
echo PHP_EOL . "Captured img tags:";
print_r($matches[1]);
echo PHP_EOL . "Captured src values:";
print_r($matches[2]);

输出结果:

Matches:Array
(
    [0] => Array
        (
            [0] => <img width src = one height>
            [1] => <img src=two height>
            [2] => <img width src="three">
            [3] => <img src = 'four' />
            [4] => <img src =five>
        )

    [1] => Array
        (
            [0] => <img width src = one height>
            [1] => <img src=two height>
            [2] => <img width src="three">
            [3] => <img src = 'four' />
            [4] => <img src =five>
        )

    [2] => Array
        (
            [0] => one
            [1] => two
            [2] => three
            [3] => four
            [4] => five
        )

)
Captured img tags:Array
(
    [0] => <img width src = one height>
    [1] => <img src=two height>
    [2] => <img width src="three">
    [3] => <img src = 'four' />
    [4] => <img src =five>
)
Captured src values:Array
(
    [0] => one
    [1] => two
    [2] => three
    [3] => four
    [4] => five
)

说明

  • 分支重置组(?|...)内部的两个分支,各自的捕获组(.+?)会被视为同一个分组(编号为2),不管匹配的是带引号还是无引号的src值,都会被存入$matches[2];
  • 同时保留了原正则对完整<img>标签的捕获(分组1),满足需求;
  • 无需再手动复制分组数据,简化了后续处理逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 04:54:55