Signature
mb_ereg_search_regs(?string $pattern = null, ?string $options = null): array|falsePurpose
mb_ereg_search_regs() runs a multibyte-aware regular expression against a string that you registered earlier and returns the text it found. Unlike mb_ereg(), which takes the subject on every call, this function belongs to a stateful search family. You prepare a string and a pattern once with mb_ereg_search_init(), then call the search functions repeatedly. Each successful call moves an internal position forward, so the next call continues after the previous match.
The return value is an array: element 0 is the whole match, element 1 is the first parenthesised group, element 2 is the second group, and so on. That makes it convenient for tokenising or scanning text that contains characters outside ASCII.
Signature
Parameters and defaults
$patternis the search pattern, written without delimiters. It defaults tonull, which means the pattern stored by the lastmb_ereg_search_init()call is reused.$optionsis a string of option letters, explained undermb_regex_set_options(). It defaults tonull, which keeps the current options. For instance,'i'requests case-insensitive matching.
Since PHP 8.0.0 both parameters are explicitly nullable.
The character encoding is the internal encoding, or whatever mb_regex_encoding() has set. Make sure it matches your string, usually UTF-8.
Return value and failure
On success you get a list with the matched substring first, followed by one entry per capture group. On error the function returns false. In practice you will also see false when the remaining part of the string contains no further match, which is what ends a scanning loop. A search must be initialised with a subject string before this function can work.
Example 1: first match and position
The first call finds the first number-and-word pair. Afterwards mb_ereg_search_getpos() reports where the next search will start. That position is a byte offset, not a character count.
mb_regex_encoding('UTF-8');
mb_ereg_search_init('Order: 42 apples, 7 pears', '(\d+) (\w+)');
$m = mb_ereg_search_regs();
echo json_encode($m, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
echo mb_ereg_search_getpos(), "\n";["42 apples","42","apples"] 16
Example 2: scanning every match
Because each call continues where the last one stopped, a while loop visits all matches. The loop ends when the function returns false. The text below uses Japanese characters, so the capture groups hold multibyte strings.
mb_regex_encoding('UTF-8');
mb_ereg_search_init('東京=13; 大阪=27; 京都=26', '([^=; ]+)=(\d+)');
$pairs = [];
while ($m = mb_ereg_search_regs()) {
$pairs[$m[1]] = (int) $m[2];
}
echo json_encode($pairs, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";{"東京":13,"大阪":27,"京都":26}
Example 3: pattern and options in the call
You may supply the pattern and options directly. Here the subject is registered without a pattern, and the call passes 'i' for case-insensitive matching. The optional middle group does not take part in the match, so its slot holds false.
mb_regex_encoding('UTF-8');
mb_ereg_search_init('Cat');
$m = mb_ereg_search_regs('(c)(x)?(a)', 'i');
echo json_encode($m, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";["Ca","C",false,"a"]
Edge cases
- Non-participating groups. A group that did not match appears as
false, not as an empty string. Compare with===before using the value. - Byte positions. The internal position is measured in bytes. Do not mix it with
mb_substr()character offsets without converting. - Shared state. The string, pattern and position live in global per-request state. Starting another
mb_ereg_search_init()replaces them, so two interleaved scans will disturb each other. - Empty matches. A pattern that can match an empty string is a poor fit for a scanning loop. Write patterns that consume at least one character.
- Named groups. Oniguruma supports named groups. Be ready for extra keys in the result when you use them, and test the exact shape.
Common mistakes
- Forgetting to initialise. Calling the function before
mb_ereg_search_init()leaves it with nothing to search. - Using delimiters. Write
'(\d+)', not'/(\d+)/'. Themb_eregfamily does not use PCRE-style delimiters. - Treating
falseonly as an error. In a loop,falseis the normal stop signal. - Encoding mismatch. If the regex encoding differs from the string encoding, matches may be wrong or missing. Call
mb_regex_encoding()explicitly. - Expecting
preg_match()semantics. There are no flags such asPREG_OFFSET_CAPTURE, and the subject is not passed on each call.
Related functions
mb_ereg_search_init()sets the subject string, pattern and options.mb_ereg_search()only reports whether a match exists.mb_ereg_search_pos()returns the byte position and length of the match.mb_ereg_search_getregs()retrieves the groups of the last match.mb_ereg_search_getpos()andmb_ereg_search_setpos()read and move the position.mb_regex_encoding()andmb_regex_set_options()control encoding and options.
Recap
Initialise the search with mb_ereg_search_init(), then call mb_ereg_search_regs() to receive the whole match plus capture groups as an array. Each success advances the internal byte position, false signals an error or no further match, and unmatched groups appear as false. Keep the regex encoding aligned with your data and avoid interleaving separate searches.
Tested examples
mb_regex_encoding('UTF-8');
mb_ereg_search_init('Order: 42 apples, 7 pears', '(\d+) (\w+)');
$m = mb_ereg_search_regs();
echo json_encode($m, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
echo mb_ereg_search_getpos(), "\n";
["42 apples","42","apples"] 16
mb_regex_encoding('UTF-8');
mb_ereg_search_init('東京=13; 大阪=27; 京都=26', '([^=; ]+)=(\d+)');
$pairs = [];
while ($m = mb_ereg_search_regs()) {
$pairs[$m[1]] = (int) $m[2];
}
echo json_encode($pairs, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
{"東京":13,"大阪":27,"京都":26}
mb_regex_encoding('UTF-8');
mb_ereg_search_init('Cat');
$m = mb_ereg_search_regs('(c)(x)?(a)', 'i');
echo json_encode($m, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
["Ca","C",false,"a"]