Strspn: примеры (PHP)

Использование strspn для проверки символов в PHP
Раздел: Работа со строками
strspn(string string, string characters [, int offset [, int length]]): int
Описание функции strspn

Функция strspn в PHP определяет длину начального сегмента строки, который полностью состоит из символов, указанных в параметре маски. Эта функция используется для проверки или извлечения данных, когда требуется определить, с каких допустимых символов начинается строка.

Аргументы функции
  • string $string - исследуемая строка.
  • string $characters - строка, содержащая список разрешенных символов.
  • int $offset (необязательный) - позиция в строке, с которой начинается поиск. По умолчанию 0. В PHP 8+ отрицательные значения отсчитываются от конца строки.
  • int $length (необязательный) - максимальная длина проверяемого сегмента строки. По умолчанию проверяется вся строка от offset до конца.

Функция возвращает целое число - длину начального сегмента строки, состоящего только из символов из списка $characters.

Простые примеры использования

Пример с базовым использованием:

echo strspn('12345abc', '0123456789');
5

Пример с указанием offset:

echo strspn('абв123', '123', 3);
3

Пример с offset и length:

echo strspn('aaabbbccc', 'a', 0, 5);
3

Пример, когда строка начинается с недопустимого символа:

echo strspn('xyz123', '1234567890');
0

Пример с отрицательным offset (PHP 8+):

echo strspn('абвгде', 'абв', -6, 3);
3
Похожие функции в PHP
  • strcspn() - вычисляет длину начального сегмента строки, который не содержит символов из указанного набора. Используется, когда нужно найти позицию первого запрещенного символа.
  • preg_match() с регулярным выражением, например, '/^[0-9]+/' - более гибкое решение для сложных проверок, но менее эффективное для простых случаев.
  • ctype_* функции (ctype_alnum, ctype_digit и др.) - проверяют всю строку на соответствие критериям, но не вычисляют длину сегмента.

strspn предпочтительнее для случаев, когда важно знать, сколько начальных символов удовлетворяют условию, а не просто факт соответствия.

Типичные ошибки

1. Передача пустой строки в качестве маски символов приводит к возврату 0 на всех версиях PHP:

var_dump(strspn('test', ''));
int(0)

2. Указание offset за пределами длины строки вызывает предупреждение и возврат false (до PHP 8) или 0 (PHP 8+):

echo strspn('abc', 'a', 10);
Warning: strspn(): Offset not contained in string in ...
0

3. Неявное преобразование типов, если переданы не строковые аргументы. С PHP 8 это может вызвать TypeError:

echo strspn(['string'], 's');
Warning: strspn() expects parameter 1 to be string, array given in ...

4. Ожидание, что функция проверяет вхождение символов в любом месте строки, а не только в начале:

$result = strspn('abc123def', '123');
// Ожидание: 3, реальность: 0, т.к. строка начинается не с цифр
echo $result;
0
Изменения в версиях PHP

В PHP 8.0 поведение функции при передаче отрицательного значения в параметре offset было изменено. Теперь отрицательный offset интерпретируется как смещение от конца строки. В предыдущих версиях отрицательный offset приводил к возврату 0 без вывода ошибки.

// PHP 8+
echo strspn('abcdef', 'abc', -3); // Проверка начинается с 'd'
// PHP 7.4 и ранее
// echo strspn('abcdef', 'abc', -3); возвращало 0
0

Также в PHP 8.0 функции стали строго типизированными. Передача аргументов несовместимого типа может вызывать TypeError вместо предупреждения.

Расширенные примеры
Валидация числового префикса

Проверка, что номер телефона начинается с кода страны:

Пример php
$phone = '+79161234567';
$countryCodeLength = strspn($phone, '+0123456789', 0, 3);
if ($countryCodeLength === 3 && $phone[1] === '7' && $phone[2] === '9') {
    echo 'Российский номер';
} else {
    echo 'Другой формат';
}
Российский номер
Извлечение подстроки с допустимыми символами

Получение числовой части из смешанной строки:

Пример php
$data = '1234abc567';
$len = strspn($data, '0123456789');
$numericPrefix = substr($data, 0, $len);
echo $numericPrefix;
1234
Проверка нескольких наборов символов

Определение длины префикса, состоящего из букв или цифр:

Пример php
function custom_strspn($str, $masks) {
    foreach ($masks as $mask) {
        $len = strspn($str, $mask);
        if ($len > 0) return $len;
    }
    return 0;
}
echo custom_strspn('ABC123', ['ABCDEFGHIJKLMNOPQRSTUVWXYZ', '0123456789']);
3
Обработка многобайтовых строк

Стандартная strspn не поддерживает UTF-8. Решение с mbstring:

Пример php
function mb_strspn($str, $mask) {
    $len = 0;
    $strLen = mb_strlen($str);
    while ($len < $strLen && mb_strpos($mask, mb_substr($str, $len, 1)) !== false) {
        $len++;
    }
    return $len;
}
echo mb_strspn('абвгде', 'абв');
3
Поиск позиции первого несовпадающего символа

Комбинация с strlen для поиска позиции:

Пример php
$str = '0000123';
$validLen = strspn($str, '0');
if ($validLen < strlen($str)) {
    echo 'Первый ненулевой символ на позиции: ' . $validLen;
} else {
    echo 'Строка состоит только из нулей';
}
Первый ненулевой символ на позиции: 4
Аналоги в других языках

Strspn в Python

Метод строки str.lstrip() с передачей набора символов удаляет их с начала, но не возвращает длину. Для точного аналога нужна своя реализация:

s = '12345abc'
from itertools import takewhile
length = len(list(takewhile(lambda ch: ch in '0123456789', s)))
print(length)
5

Strspn в Javascript

Прямого аналога нет. Реализация через цикл или регулярное выражение:

let str = '12345abc';
let mask = '0123456789';
let length = 0;
while(mask.includes(str[length])) length++;
console.log(length);
5

Strspn в MySQL

Функция REGEXP_INSTR() или LOCATE() с подзапросом, но решение неочевидное:

SELECT LENGTH(SUBSTRING('12345abc' FROM 1 FOR 
  (SELECT MIN(pos) FROM 
    (SELECT 1 AS pos WHERE SUBSTRING('12345abc', 1, 1) NOT REGEXP '^[0-9]' 
     UNION ALL SELECT 2 WHERE SUBSTRING('12345abc', 2, 1) NOT REGEXP '^[0-9]'
     UNION ALL SELECT 3 WHERE SUBSTRING('12345abc', 3, 1) NOT REGEXP '^[0-9]'
     UNION ALL SELECT 4 WHERE SUBSTRING('12345abc', 4, 1) NOT REGEXP '^[0-9]'
     UNION ALL SELECT 5 WHERE SUBSTRING('12345abc', 5, 1) NOT REGEXP '^[0-9]'
     UNION ALL SELECT 6 WHERE SUBSTRING('12345abc', 6, 1) NOT REGEXP '^[0-9]') AS t
  ))
) AS length;
5

PHP strspn function comments

En
Strspn Finds the length of the initial segment of a string consisting entirely of characters contained within a given mask