Signature
mb_ereg_search_init(string $string, ?string $pattern = null, ?string $options = null): boolPurpose
mb_ereg_search_init() stores a subject string, and optionally a pattern and options, in internal state belonging to the mbstring regex engine. The other functions in the family then work on that stored state: mb_ereg_search(), mb_ereg_search_pos() and mb_ereg_search_regs(). Each call to one of these finds the next match and moves an internal cursor forward. You get an incremental, cursor-style scan over a multibyte string without passing the string and pattern every time.
The character encoding used for matching is the current regex encoding. That is the internal encoding, or whatever you set with mb_regex_encoding().
Signature
Parameters and defaults
$string: the subject text to search. It is required.$pattern: the regular expression, written without delimiters. It has been nullable since PHP 8.0.0 and defaults tonull.$options: option letters such asifor case-insensitive matching. They are explained undermb_regex_set_options(). It is nullable and defaults tonull.
Return value and failure
The function returns true on success and false on failure, for example when the pattern cannot be compiled. It does not return matches. It only prepares the search, so you must call one of the search functions afterwards. Check the result with a strict comparison if your patterns come from outside your code.
Example 1: collecting every match
After initialising, loop on mb_ereg_search_regs(). It returns an array for each match and false once nothing more is found.
mb_regex_encoding('UTF-8');
mb_ereg_search_init('cat bat rat', '[cbr]at');
$found = [];
while (($regs = mb_ereg_search_regs()) !== false) {
$found[] = $regs[0];
}
echo json_encode($found), "\n";["cat","bat","rat"]
Example 2: byte positions in multibyte text
mb_ereg_search_pos() reports a match as a pair of byte offset and byte length. With accented characters that differs from the character count, because é takes two bytes in UTF-8.
mb_regex_encoding('UTF-8');
mb_ereg_search_init('café olé', 'é');
$positions = [];
while (($pos = mb_ereg_search_pos()) !== false) {
$positions[] = $pos;
}
echo json_encode($positions), "\n";[[3,2],[8,2]]
Example 3: options and capture groups
The third argument turns on case-insensitive matching here. The capture group is read from index 1 of the array returned by mb_ereg_search_regs().
mb_regex_encoding('UTF-8');
$ok = mb_ereg_search_init('ID=42; id=7; Id=19', 'id=([0-9]+)', 'i');
$ids = [];
while (($regs = mb_ereg_search_regs()) !== false) {
$ids[] = $regs[1];
}
echo json_encode(['init' => $ok, 'ids' => $ids]), "\n";{"init":true,"ids":["42","7","19"]}
Edge cases
- Shared state. The string, pattern and cursor are stored once for the whole request. Calling
mb_ereg_search_init()again replaces them and starts a new scan from the beginning. Do not interleave two independent scans. - Omitting the pattern. Because
$patternis nullable, you can supply only a new string. Your code is easier to follow, though, if you pass the pattern explicitly each time you initialise. - Byte offsets. Positions from
mb_ereg_search_pos()and the cursor are byte-based. Do not use them as character indexes withmb_substr(). Usesubstr()or convert them first. - Empty matches. A pattern that can match an empty string, such as
x*, may not advance the way you expect. Prefer patterns that consume at least one character when you loop. - Encoding. Match behaviour depends on the regex encoding. If the subject is not valid in that encoding, results can be wrong or the search can fail.
Common mistakes
- Not initialising first. Calling a search function without an earlier successful init gives no meaningful scan.
- Loose loop conditions.
while ($regs = mb_ereg_search_regs())works for non-empty arrays, but an explicit!== falsestates the intent more clearly. The same applies tomb_ereg_search(), which returns a boolean. - Using delimiters. The
mb_eregfamily takes bare patterns, not/pattern/i. Put flags in$options. - Mixing up with preg.
preg_match_all()returns every match in one call. The mb_ereg search functions step through them one at a time. - Ignoring the return value. If
falsecomes back and you carry on, later calls run against stale or missing state.
Related functions
mb_ereg_search()tests for the next match and advances the cursor.mb_ereg_search_pos()returns the byte offset and length of the next match.mb_ereg_search_regs()returns the next match with its capture groups.mb_regex_encoding()sets or reads the regex character encoding.mb_regex_set_options()explains the option letters.
Recap
mb_ereg_search_init() loads a string, a pattern and options into shared state and returns true or false. Follow it with mb_ereg_search_regs() or mb_ereg_search_pos() in a loop to walk through matches. Remember that offsets are in bytes, that the state is global and that the pattern has no delimiters.
Tested examples
mb_regex_encoding('UTF-8');
mb_ereg_search_init('cat bat rat', '[cbr]at');
$found = [];
while (($regs = mb_ereg_search_regs()) !== false) {
$found[] = $regs[0];
}
echo json_encode($found), "\n";["cat","bat","rat"]
mb_regex_encoding('UTF-8');
mb_ereg_search_init('café olé', 'é');
$positions = [];
while (($pos = mb_ereg_search_pos()) !== false) {
$positions[] = $pos;
}
echo json_encode($positions), "\n";[[3,2],[8,2]]
mb_regex_encoding('UTF-8');
$ok = mb_ereg_search_init('ID=42; id=7; Id=19', 'id=([0-9]+)', 'i');
$ids = [];
while (($regs = mb_ereg_search_regs()) !== false) {
$ids[] = $regs[1];
}
echo json_encode(['init' => $ok, 'ids' => $ids]), "\n";{"init":true,"ids":["42","7","19"]}