Signature
mb_ereg_search_setpos(int $offset): boolPurpose
mb_ereg_search_setpos() moves the starting point for the next match in PHP's stateful multibyte regex search API. You first load a subject string and a pattern with mb_ereg_search_init(). Each later call to mb_ereg_search(), mb_ereg_search_pos() or mb_ereg_search_regs() continues from an internal position. This function lets you set that position yourself, so you can skip a header, rewind to a known place, or resume after a match you have already processed.
Because the search state is stored inside the extension and not in a variable you pass around, it is easy to lose track of where you are. mb_ereg_search_setpos() makes the starting point explicit.
Signature
Parameters and defaults
$offset: the position at which the next search should start. It has no default, so you must always pass it.- A non-negative value is a position from the start of the string.
- A negative value counts from the end of the string. Support for negative offsets was added in PHP 7.1.0.
The manual notes that the internal encoding, or the encoding chosen with mb_regex_encoding(), is used as the character encoding for this function. In practice, the offsets that mb_ereg_search_pos() and mb_ereg_search_getpos() report are positions into the underlying string bytes. For that reason, prefer offsets that came from those functions over offsets you calculate with mb_strlen(). The examples below use ASCII text so the numbers are the same either way.
Return value and failures
The function returns true on success and false on failure. In PHP 8, an offset that falls outside the current subject string, either too large or a negative value that reaches before the start, raises a ValueError and does not return false. An offset equal to the string length is accepted and positions the search at the very end.
Example 1: skip ahead to a later match
The subject contains cat twice. Starting at offset 4 skips the first one, so the next search finds the second. mb_ereg_search_pos() returns the start position and the length of the match.
mb_regex_encoding('UTF-8');
mb_ereg_search_init('cat dog cat', 'cat');
$ok = mb_ereg_search_setpos(4);
$match = mb_ereg_search_pos();
echo json_encode([$ok, $match], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . "\n";[true,[8,3]]
Example 2: rewind with a negative offset
A first search consumes the first cat and moves the internal position forward. A negative offset then counts back from the end of the string. With an 11-byte subject, -3 means position 8.
mb_regex_encoding('UTF-8');
mb_ereg_search_init('cat dog cat', 'cat');
$first = mb_ereg_search_pos();
$ok = mb_ereg_search_setpos(-3);
$second = mb_ereg_search_pos();
echo json_encode([$first, $ok, $second], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . "\n";[[0,3],true,[8,3]]
Example 3: boundaries and errors
The subject length (11) is the largest valid offset. One past that is out of range and throws a ValueError, which you can catch.
mb_regex_encoding('UTF-8');
mb_ereg_search_init('cat dog cat', 'cat');
$atEnd = mb_ereg_search_setpos(11);
try {
mb_ereg_search_setpos(12);
$tooFar = 'no error';
} catch (ValueError $e) {
$tooFar = 'ValueError';
}
echo json_encode(['atEnd' => $atEnd, 'tooFar' => $tooFar], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . "\n";{"atEnd":true,"tooFar":"ValueError"}
Edge cases
- Start of a new search: calling
mb_ereg_search_init()loads a new subject and pattern, and the search begins from the start again. Set the position after initializing, not before. - End of the string: setting the position to the string length succeeds, but a following search finds nothing because no text remains.
- Negative offsets:
-1refers to the last position counted from the end. A negative value larger in magnitude than the string length is out of range. - Multibyte text: positions are not guaranteed to be character counts. Landing in the middle of a multibyte character can give confusing results, so reuse offsets reported by the search functions.
Common mistakes
- Expecting a
falsereturn for bad offsets. In PHP 8, a bad offset throwsValueError. Wrap untrusted offsets intry/catchor validate them first. - Using it without
mb_ereg_search_init(). The function configures state for a search, so it only makes sense after a subject string has been loaded. - Mixing it up with the
offsetofmb_ereg(). Ordinarymb_ereg()takes no start offset. This function belongs to the stateful search family only. - Computing offsets with
mb_strlen()ormb_strpos(). Those count characters, whereas the search positions are byte positions. Usemb_ereg_search_getpos()to read the current position and pass that value back later. - Forgetting that each match moves the position. If you need to run a second pass over the same text, rewind with
mb_ereg_search_setpos(0).
Related functions
mb_ereg_search_init()sets the subject string and pattern.mb_ereg_search()tests whether the pattern matches from the current position.mb_ereg_search_pos()returns the start and length of the next match.mb_ereg_search_regs()returns the match and its capture groups.mb_ereg_search_getpos()reads the current position.mb_regex_encoding()gets or sets the regex character encoding.
Recap
mb_ereg_search_setpos() takes one integer, sets where the next stateful multibyte regex search begins, and returns true on success. Negative offsets count from the end, and offsets outside the subject string throw a ValueError in PHP 8. Initialize the search first, and store positions reported by PHP instead of recalculating them with character-based functions.
Tested examples
mb_regex_encoding('UTF-8');
mb_ereg_search_init('cat dog cat', 'cat');
$ok = mb_ereg_search_setpos(4);
$match = mb_ereg_search_pos();
echo json_encode([$ok, $match], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . "\n";
[true,[8,3]]
mb_regex_encoding('UTF-8');
mb_ereg_search_init('cat dog cat', 'cat');
$first = mb_ereg_search_pos();
$ok = mb_ereg_search_setpos(-3);
$second = mb_ereg_search_pos();
echo json_encode([$first, $ok, $second], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . "\n";
[[0,3],true,[8,3]]
mb_regex_encoding('UTF-8');
mb_ereg_search_init('cat dog cat', 'cat');
$atEnd = mb_ereg_search_setpos(11);
try {
mb_ereg_search_setpos(12);
$tooFar = 'no error';
} catch (ValueError $e) {
$tooFar = 'ValueError';
}
echo json_encode(['atEnd' => $atEnd, 'tooFar' => $tooFar], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . "\n";
{"atEnd":true,"tooFar":"ValueError"}