Multibyte strings7 min readExamples run on PHP 8.5.10

mb_ereg_match()

Learn how mb_ereg_match() checks whether a multibyte string matches a regular expression at its start, with examples, edge cases and common mistakes.

Signature

mb_ereg_match(string $pattern, string $string, ?string $options = null): bool
Available since PHP 4.2.07.48.08.18.28.38.48.5All versions →

Purpose

mb_ereg_match() answers a yes-or-no question: does a multibyte string match a regular expression, starting at its first character? It belongs to the mb_ereg family, which treats text as characters in a given encoding instead of raw bytes. That makes . and character classes behave sensibly with accented letters and other non-ASCII text.

The function returns only a boolean. It does not return captured groups or offsets. If you need the matched pieces, look at mb_ereg() instead.

Signature

Parameters and defaults

  • $pattern is the regular expression. It is written without delimiters, unlike preg_match(). So you write [0-9]+, not /[0-9]+/.
  • $string is the text being tested.
  • $options is an optional string of option letters. The manual points to mb_regex_set_options() for what the letters mean. The default is null, and the parameter has been nullable since PHP 8.0.0. A common option is i, which ignores case.

The character encoding comes from the internal encoding, or from the one you set with mb_regex_encoding(). If your text is UTF-8, set that explicitly so the result does not depend on environment settings.

Return value and failure cases

The function returns true when the string matches the pattern and false when it does not. A false therefore means "no match". It is not a separate error signal. A malformed pattern is a programming mistake, so test your patterns on known inputs before relying on them.

The most important rule: start-anchored matching

The manual notes that the pattern is matched only at the beginning of the string. It behaves as if the match must begin at the first character. It does not behave as if the whole string must match. A pattern like hello matches hello world, but world does not match it, because world is not at the start.

Example
<?php
var_dump(mb_ereg_match('[a-z]+', 'hello world'));
var_dump(mb_ereg_match('world', 'hello world'));
Output
bool(true)
bool(false)

The first call matches the leading letters. The second fails because the match cannot begin in the middle.

Working with multibyte text

When the encoding is set correctly, each accented letter counts as one character. In the example below, ....$ means "exactly four characters from the start to the end". The word żółw has four characters but more than four bytes in UTF-8.

Example
<?php
mb_regex_encoding('UTF-8');
$word = 'żółw';
echo json_encode([
    'prefix' => mb_ereg_match('żó', $word),
    'dot_count' => mb_ereg_match('....$', $word),
    'middle' => mb_ereg_match('ół', $word),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"prefix":true,"dot_count":true,"middle":false}

The prefix matches. The four-dot pattern matches because the engine counts characters. The middle fragment ół is present in the word but not at the start, so it returns false.

Requiring the whole string to match

Because only the start is anchored, add an end anchor such as $ when the entire value must fit the pattern. The example also shows the i option for case-insensitive matching.

Example
<?php
mb_regex_encoding('UTF-8');
$inputs = ['digits' => '2024', 'suffix' => '2024abc', 'prefix' => 'abc2024'];
$result = [];
foreach ($inputs as $name => $value) {
    $result[$name] = mb_ereg_match('[0-9]+$', $value);
}
$result['ci'] = mb_ereg_match('HELLO', 'hello world', 'i');
echo json_encode($result), "\n";
Output
{"digits":true,"suffix":false,"prefix":false,"ci":true}

2024abc fails because the digits are not followed by the end of the string. abc2024 fails because it does not start with a digit.

Edge cases

  • Empty matches: a pattern that can match zero characters, such as a*, matches at the start of any string. That includes an empty one. Use + when at least one character is required.
  • Encoding mismatch: if the regex encoding does not agree with the real encoding of the string, character counting and class matching can give surprising results. Set mb_regex_encoding() explicitly.
  • Option state: the $options argument is a string of letters, not a bit mask. Check mb_regex_set_options() for the supported letters before using any besides the familiar i.

Common mistakes

  1. Adding delimiters. Writing '/abc/' makes the slashes part of the pattern. Use 'abc'.
  2. Expecting a search anywhere. This function does not scan the string. For a match anywhere, put .* at the front of the pattern, or use a function designed for searching.
  3. Assuming a full match. Without $, trailing text is ignored.
  4. Expecting captures. The return value is only true or false.
  5. Mixing it up with preg_match(). The preg_* functions use delimiters and PCRE syntax, while this function uses the multibyte regex engine and its own option letters.
  • mb_ereg() runs a multibyte regex match and can provide the matched groups.
  • mb_regex_encoding() gets or sets the character encoding used by the multibyte regex functions.
  • mb_regex_set_options() explains and sets the option letters.
  • preg_match() is the PCRE-based alternative with delimiters.

Recap

Use mb_ereg_match() for a quick boolean test of whether a multibyte string begins with something matching a delimiter-free pattern. Set the regex encoding, add $ when the whole string must match, and remember that it never reports where or what matched.

Tested examples

Matching is anchored at the start
<?php
var_dump(mb_ereg_match('[a-z]+', 'hello world'));
var_dump(mb_ereg_match('world', 'hello world'));
Output
bool(true)
bool(false)
Character-aware matching with UTF-8
<?php
mb_regex_encoding('UTF-8');
$word = 'żółw';
echo json_encode([
    'prefix' => mb_ereg_match('żó', $word),
    'dot_count' => mb_ereg_match('....$', $word),
    'middle' => mb_ereg_match('ół', $word),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"prefix":true,"dot_count":true,"middle":false}
End anchor and the case-insensitive option
<?php
mb_regex_encoding('UTF-8');
$inputs = ['digits' => '2024', 'suffix' => '2024abc', 'prefix' => 'abc2024'];
$result = [];
foreach ($inputs as $name => $value) {
    $result[$name] = mb_ereg_match('[0-9]+$', $value);
}
$result['ci'] = mb_ereg_match('HELLO', 'hello world', 'i');
echo json_encode($result), "\n";
Output
{"digits":true,"suffix":false,"prefix":false,"ci":true}