Почему preg_match_all возвращает пустой массив?

В функции "getStartPositionInclude" регулярное выражение возвращает пустой массив, если параметр $str является многобайтовой строкой (содержит символы Кириллицы), флаг /u в регулярке присутствует, а если параметр $str содержит только символы английского алфавита, то работает корректно, т.е в переменную-массив $words записываются слова из $str. Почему это происходит и как можно исправить это?

function getStartPositionInclude( $str ){
    $words = [];
    preg_match_all( "/[^\W\d][\w]*/u", $str, $words );
    $words = $words[0];

    $lastWordindex = count($words) - 1;
    $positionSymbol = mb_strripos($str, $words[$lastWordindex - 1]);

    return $positionSymbol ;
}

Ответы (1 шт):

Автор решения: yar85

Токены \w и \W матчат только латинские буквы [a-zA-Z] - буквенные диапазоны других локалей, в эти токены могут быть не включены (зависит от реализации).

Собственно, \w == [a-zA-Z0-9_] и \W == [^a-zA-Z0-9_]:

\w stands for “word character”. It always matches the ASCII characters [A-Za-z0-9_]. Notice the inclusion of the underscore and digits. In most flavors that support Unicode, \w includes many characters from other scripts. There is a lot of inconsistency about which characters are actually included.
(источник)

Another special sequence that may appear at the start of a pattern is (*UCP). This has the same effect as setting the PCRE2_UCP option: it causes sequences such as \d and \w to use Unicode properties to determine character types, instead of recognizing only characters with codes less than 256 via a lookup table. (...)
Some applications that allow their users to supply patterns may wish to restrict them for security reasons. If the PCRE2_NEVER_UCP option is passed to pcre2_compile(), (*UCP) is not allowed, and its appearance in a pattern causes an error.
(источник)


  • Либо напиши в выражении что-то типа [a-zA-Zа-яА-ЯёЁ0-9_]
    (или [a-zа-яё0-9_] с флагом i)

  • Либо используй юникодовские классы (категории) расширенного PCRE типа \p{L}
    (предварительно уточнив, есть ли их поддержка в используемой тобой версии PHP, а то мало ли...)


p.s.: [\w]* в конце регулярки из вопроса - это абсолютно то же самое что \w* (можно смело убрать [ ]).

→ Ссылка