Strspn: примеры (PHP)
strspn(string string, string characters [, int offset [, int length]]): intФункция 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
- 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 8.0 поведение функции при передаче отрицательного значения в параметре offset было изменено. Теперь отрицательный offset интерпретируется как смещение от конца строки. В предыдущих версиях отрицательный offset приводил к возврату 0 без вывода ошибки.
// PHP 8+
echo strspn('abcdef', 'abc', -3); // Проверка начинается с 'd'
// PHP 7.4 и ранее
// echo strspn('abcdef', 'abc', -3); возвращало 00
Также в PHP 8.0 функции стали строго типизированными. Передача аргументов несовместимого типа может вызывать TypeError вместо предупреждения.
Проверка, что номер телефона начинается с кода страны:
$phone = '+79161234567';
$countryCodeLength = strspn($phone, '+0123456789', 0, 3);
if ($countryCodeLength === 3 && $phone[1] === '7' && $phone[2] === '9') {
echo 'Российский номер';
} else {
echo 'Другой формат';
}Российский номер
Получение числовой части из смешанной строки:
$data = '1234abc567';
$len = strspn($data, '0123456789');
$numericPrefix = substr($data, 0, $len);
echo $numericPrefix;1234
Определение длины префикса, состоящего из букв или цифр:
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:
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 для поиска позиции:
$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