PHP 有效地preg_match字符串的一部分


PHP preg_match part of string efficiently

例如,给定以下函数定义:

function match($subject, $pattern, $offset);

这些测试应成功:

$subject = "23 is a number, so is 10";
match($subject, '[0-9]+', 0) == '23';
match($subject, '[0-9]+', 3) == false;
match($subject, '[0-9]+', 6) == false;
match($subject, '[0-9]+', 8) == false;
match($subject, '[a-z]+', 0) == false;
match($subject, '[a-z]+', 3) == 'is';
match($subject, '[a-z]+', 6) == 'a';
match($subject, '[a-z]+', 8) == 'number';

一种可能的方法是使用 ^ 匹配从 $offset 开始的子字符串:

function match($subject, $pattern, $offset) {
    if (preg_match("/^($pattern)/", substr($subject, offset), $matches)) {
        return $matches[1];
    }
    return false;
}

这将创建字符串的副本,这当然对于大型字符串无效。

实现match的另一种可能方法是:

function match($subject, $pattern, $offset) {
    if (preg_match("/($pattern)/", $subject, $matches, PREG_OFFSET_CAPTURE, $offset)) {
        if ($matches[1][1] == $offset) {
            return $matches[1][0];
        }
    }
    return false;
}

但即使第一个字符不匹配,这也会继续尝试匹配。

问题:如何有效地匹配字符串的一部分?

或者也许更好,是否可以断言偏移位置?就像^断言字符串的开头一样。

你可以尝试这样的事情:

function match($subject, $pattern, $offset) {
    if (preg_match('/^.{' . $offset . '}'K' . $pattern . '/us', $subject, $match))
        return $match[0];
    return false;
}

更好!您可以使用在偏移量处匹配的'G锚点:

function match($subject, $pattern, $offset) {
    if (preg_match('/'G' . $pattern . '/us', $subject, $match, 0, $offset))
        return $match[0];
    return false;
}