如何使用正则表达式获取包含所有图像数字和图像字母的数组?

时间:2019-06-04 09:05:11

标签: php regex

我需要基于以下格式的表达式,获取所有相关图像,以PHP解析html:

(fig. 8a-c, 9b-c)

我想使用正则表达式来捕获它,以便输出诸如以下的数组:

array(
[8] => [a,b,c],
[9] => [b,c])

表达式可以是这样的:

(fig. 8)
(fig. 8,9)
(fig. 11a, b)

这是我目前使用的正则表达式,但似乎并非在每种情况下都有效:

https://regex101.com/r/ShqlnY/3/

您能帮我得到一个包含所有包含图像的数组吗?谢谢

3 个答案:

答案 0 :(得分:1)

谢谢,我最终得到了这样的正则表达式:

'/(?:\(fig\.\h*|\G(?!^))(\d+)([a-z])?(?:-([a-z])?)?(?:,\h*)?(?=[^)]*\))/m'

preg_match_all

一起使用

答案 1 :(得分:0)

也许对于示例数据,您可以使用range和具有3个捕获组的模式,其中第三组是可选的。

如果第三组不存在,则返回数组中的单个值,否则使用第二组和第三组创建范围。

(?:^\(fig\.\h*|\G(?!^))(\d+)([a-z])(?:-([a-z])?)?(?:,\h*)?(?=[^)]*\))
  • (?:非捕获组
    • ^\(fig\.\h*匹配字符串的开头和(图,后跟0+个水平空格
    • |
    • \G(?!^)在上一场比赛的末尾而不是在开始时断言
  • )关闭非捕获组
  • (\d+)([a-z])在组1中捕获1个以上的数字,在组2中捕获a-z
  • (?:非捕获组
    • -([a-z])?
  • )?关闭非捕获组并设置为可选
  • (?:,\h*)?匹配可选的,和0+个水平空白字符
  • (?=[^)]*\))断言右边是右括号

Regex demo

例如:

$pattern = "/(?:^\(fig\.\h*|\G(?!^))(\d+)([a-z])(?:-([a-z])?)?(?:,\h*)?(?=[^)]*\))/m";
$str = '(fig. 8a-c, 9b-c)
(fig. 8)
(fig. 8,9)
(fig. 11a, b)';
preg_match_all($pattern, $str, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE, 0);

$matches = array_map(function($x){
    if (isset($x[3][0])) {
        return [
            $x[1][0] => range($x[2][0], $x[3][0]),
            "start" => $x[1][1],
            "end" => $x[3][1]
        ];
    }
    return [
        $x[1][0] => [$x[2][1]],
        "start" => $x[2][0],
        "end" => $x[1][1]
    ];

}, $matches);

print_r($matches);

结果

Array
(
    [0] => Array
        (
            [8] => Array
                (
                    [0] => a
                    [1] => b
                    [2] => c
                )

            [start] => 6
            [end] => 9
        )

    [1] => Array
        (
            [9] => Array
                (
                    [0] => b
                    [1] => c
                )

            [start] => 12
            [end] => 15
        )

)

查看php demo

答案 2 :(得分:0)

您可以使用

'~(?:\G(?!^),\s*|\(fig\.)\s*\K([0-9]{1,3})([a-z]-[a-z])~'

preg_match_all一起从(fig. ...)子字符串中获取所有字符范围(请参阅regex demo),然后使用此后处理代码:

$rx = "~(?:\G(?!^),\s*|\(fig\.)\s*\K([0-9]{1,3})([a-z]-[a-z])~";
$s = "(fig. 8a-c, 9b-c)";
preg_match_all($rx, $s, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER, 0);

foreach ($matches as $m) {
    $result = [];
    $result[] = $m[0][1]; // Position of the match
    $result[] = $m[1][0]; // The number
    $kv = explode("-", $m[2][0]);
    $result = array_merge($result, buildNumChain($kv));
    print_r($result);
}

function buildNumChain($arr) {
    $ret = [];
    foreach(range($arr[0], $arr[1]) as $letter) {
        $ret[] = $letter;
    }
    return $ret;
}

输出:

Array ( [0] => 6  [1] => 8 [2] => a [3] => b [4] => c )
Array ( [0] => 12 [1] => 9 [2] => b [3] => c )

请参见PHP demo

正则表达式详细信息

  • (?:\G(?!^),\s*|\(fig\.)-(fig.或上一个匹配项的末尾+ ,和0+空格
  • \s*-超过0个空格
  • \K-匹配重置运算符
  • ([0-9]{1,3})-第1组:1到3位数字
  • ([a-z]-[a-z])-第2组:一个小写字母-和一个小写字母。