Signature
strspn(string $string, string $characters, int $offset = 0, ?int $length = null): intPurpose
strspn() counts how many bytes at the start of a string are all members of a set of allowed characters. It stops at the first byte that is not in the set and returns the count so far. It is a small, fast tool for tokenizing: skip a run of digits, measure a run of whitespace, or check that a value contains only permitted characters.
Signature
Parameters and defaults
$string: the text to examine.$characters: the allowed characters, written as a plain list. Order and duplicates do not matter. The list is literal, so"a-z"means the three charactersa,-andz, not a range.$offset: where to start. The default is0. A negative value counts from the end of the string.$length: how many bytes to examine after the starting position. The defaultnullmeans "to the end". A negative value stops that many bytes before the end of the string.
When you pass $offset or $length, the result behaves as if you had called strspn(substr($string, $offset, $length), $characters). The returned count is measured from the starting position, not from the beginning of the original string.
Return value and failure cases
The function always returns an int: the length of the initial matching segment. If the very first examined byte is not allowed, the result is 0. If every examined byte is allowed, the result equals the length of the examined part. The function does not return false for a non-matching string. Because $length is nullable since PHP 8.0, passing null explicitly is valid.
Example 1: basic runs
The first call counts the leading digits in a sentence. The second shows that a string which does not start with an allowed byte gives 0. The third shows that the set can contain several characters.
echo strspn("42 is the answer", "1234567890"), "\n";
echo strspn("foo", "o"), "\n";
echo strspn("aabbcc", "ab"), "\n";2 0 4
Example 2: offset and length
Here each call examines a different slice. Remember that the count restarts at the offset.
$s = "foo";
echo json_encode([
strspn($s, "o", 1, 2),
strspn($s, "o", 1, 1),
strspn("abcdef", "abcdef", -3),
strspn("abcdefxyz", "abcdef", 0, -3),
strspn("abc123", "abc", 3)
]) . "\n";[2,1,3,6,0]
The -3 offset starts at def. The -3 length in the fourth call leaves out the last three bytes, so only abcdef is examined.
Example 3: validating a whole string
To test that every byte is allowed, compare the result with strlen(). Guard against the empty string if you do not want it to count as valid.
function isHex(string $value): bool {
return $value !== '' && strspn($value, '0123456789abcdefABCDEF') === strlen($value);
}
echo json_encode([isHex('ff00AA'), isHex('12xz'), isHex('')]) . "\n";[true,false,false]
Edge cases
- Case sensitivity:
strspn("ABC", "abc")is0. Include both cases in the mask when you need both. - Bytes, not characters: the function is binary-safe and works on bytes. A multibyte UTF-8 character is several bytes, so list individual bytes only if you really intend that. For Unicode-aware checks, use
preg_match()with theumodifier. - Empty input: an empty string gives
0. With an empty mask nothing is allowed, so the result is also0. - Whole-string check:
strspn($s, $mask) === strlen($s)is also true for an empty string, because both sides are0.
Common mistakes
- Expecting ranges.
"a-z"does not mean lowercase letters. Write outabcdefghijklmnopqrstuvwxyzor usectype_lower()or a regular expression. - Reading the result as an absolute position. With a non-zero offset, add the offset back if you need an index into the original string.
- Counting matches anywhere. The function only measures the leading run. In
"ab12"with the set"12", the result is0, not2. - Confusing it with
strcspn().strspn()measures bytes that are in the set, whilestrcspn()measures bytes that are not in it. - Forgetting the empty string in validation helpers, as shown in the third example.
Related functions
strcspn()finds the length of the initial segment that does not match the mask.substr()explains how$offsetand$lengthare interpreted.strlen()is handy for whole-string comparisons.ctype_digit()andpreg_match()cover common validation tasks with different rules.strpbrk()finds the first occurrence of any character from a list.
Recap
strspn() returns how many bytes at the start of a string, or of the slice chosen by $offset and $length, belong to a given set. It is case-sensitive, byte-based and literal about the mask. It always returns an integer, so a failed match is 0, never false.
Tested examples
echo strspn("42 is the answer", "1234567890"), "\n";
echo strspn("foo", "o"), "\n";
echo strspn("aabbcc", "ab"), "\n";2 0 4
$s = "foo";
echo json_encode([
strspn($s, "o", 1, 2),
strspn($s, "o", 1, 1),
strspn("abcdef", "abcdef", -3),
strspn("abcdefxyz", "abcdef", 0, -3),
strspn("abc123", "abc", 3)
]) . "\n";[2,1,3,6,0]
function isHex(string $value): bool {
return $value !== '' && strspn($value, '0123456789abcdefABCDEF') === strlen($value);
}
echo json_encode([isHex('ff00AA'), isHex('12xz'), isHex('')]) . "\n";[true,false,false]